dvtm: Closing a shell causes window to hang on OS X 10.11
There’s several ways to get to this frozen shell problem since upgrading to 10.11. I don’t know enough about C to help, but I would take a wild guess that it relates to OS X’s new SIPS.
- Quit a window with the key binding (e.g. in my case
C-d q) - Type exit at a shell
- Open and then close the buffer mode pager thingy (e.g. in my case
C-d eto open a scrollback buffer in less which I gather has something to do with copying and pasting but I just use it for scrolling)
This causes the window to basically freeze, In essence I can spawn windows but not close them.
On @martanne’s advice I ran the following after intentionally causing the issue.

Which seemed to point to this line of code.

I’ve tried this with clean user configs (bashrc, profile etc), on two different machines and with clean installs of dvtm using the unmodified default config.
Hope someone can help because I’ve been using this thing daily for years now and I really miss it!
About this issue
- Original URL
- State: open
- Created 8 years ago
- Reactions: 2
- Comments: 26 (5 by maintainers)
Links to this issue
Commits related to this issue
- Use self-pipe instead of signal-blocking for SIGCHLD/SIGWINCH pselect() is broken on macOS. This isn't officially documented anywhere but there are hints of it in this article: https://daniel.haxx.s... — committed to rianhunter/dvtm by rianhunter 7 years ago
- Use self-pipe instead of signal-blocking for SIGCHLD/SIGWINCH pselect() is broken on macOS. This isn't officially documented anywhere but there are hints of it in this article: https://daniel.haxx.s... — committed to rianhunter/dvtm by rianhunter 7 years ago
- Use self-pipe instead of signal-blocking for SIGCHLD/SIGWINCH pselect() is broken on macOS. This isn't officially documented anywhere but there are hints of it in this article: https://daniel.haxx.s... — committed to rianhunter/dvtm by rianhunter 7 years ago
- Use self-pipe instead of signal-blocking for SIGCHLD/SIGWINCH pselect() is broken on macOS. This isn't officially documented anywhere but there are hints of it in this article: https://daniel.haxx.s... — committed to rianhunter/dvtm by rianhunter 7 years ago
- Use self-pipe instead of signal-blocking for SIGCHLD/SIGWINCH pselect() is broken on macOS. This isn't officially documented anywhere but there are hints of it in this article: https://daniel.haxx.s... — committed to kergoth/dvtm by rianhunter 7 years ago
- Use self-pipe instead of signal-blocking for SIGCHLD/SIGWINCH pselect() is broken on macOS. This isn't officially documented anywhere but there are hints of it in this article: https://daniel.haxx.s... — committed to wrp/dvtm by rianhunter 7 years ago
- Use self-pipe instead of signal-blocking for SIGCHLD/SIGWINCH pselect() is broken on macOS. This isn't officially documented anywhere but there are hints of it in this article: https://daniel.haxx.s... — committed to wrp/dvtm by rianhunter 7 years ago
- Use self-pipe instead of signal-blocking for SIGCHLD/SIGWINCH pselect() is broken on macOS. This isn't officially documented anywhere but there are hints of it in this article: https://daniel.haxx.s... — committed to cyruseuros/dvtm by rianhunter 7 years ago
- Use self-pipe instead of signal-blocking for SIGCHLD/SIGWINCH pselect() is broken on macOS. This isn't officially documented anywhere but there are hints of it in this article: https://daniel.haxx.s... — committed to mhweaver/dvtm by rianhunter 7 years ago
- Use self-pipe instead of signal-blocking for SIGCHLD/SIGWINCH pselect() is broken on macOS. This isn't officially documented anywhere but there are hints of it in this article: https://daniel.haxx.s... — committed to owm111/dvtm by rianhunter 7 years ago
I ran into this (or a similar?) problem trying to use dvtm on my macOS 10.14.5 system. I did some investigating, and I think I have made progress toward finding the root cause.
pselect()only sets the signal mask if it blocks. If any of the file descriptors are ready for reading immediately,pselect()returns right away, the signal mask is untouched, and any normally blocked signals are left pending.When I exit a shell on my Linux machine, the
read()invt_process()returns-1witherrnoset toEIO. On my Mac, it returns0to indicateEOF. This means thatvt_process()also returns0andmain()never marks the client as dead.main()doesn’t destroy the client on the next iteration, and its file descriptor is added to the set for the nextpselect().Because the file descriptor is still in the
fd_setandread()wouldn’t block onEOF, thepselect()returns immediately, the loop runs forever, andSIGCHLDis left unhandled indefinitely.I’m not sure if this is the right place to fix this (maybe this difference is related to pty setup?), but I made some small changes to
vt_process()andmain()so that the client is marked dead when it gets toEOF. Everything seems to be working correctly on both my machines. You can see my changes here: https://github.com/kendallschmit/dvtm/commit/233244fbe854f86ce05d4c697855aca35309ccccAdding
|WUNTRACEDworks for me as well 😺I spent some time this morning trying to understand why we end up in a
SIGSTOPto no avail.However browsing the source of tmux and screen it appears both pass
waitpidoptions ofWNOHANGorWUNTRACED. Indeed with the following diff I don’t hit this issue.Edit: Reading the tmux and screen sources beyond a simple grep I now see they explicitly continue processes if they are stopped. Indeed with the above diff the shell is lost if stopped when signaled via kill for example, whereas in tmux or screen it is not. So I’ll need to add a bit more logic than the overly simple diff above.
Example of where this was introduced in tmux https://github.com/tmux/tmux/commit/62d2ab3e687bfc7e0a02adedee30314b8ef1b08b
Yes, as mentioned in my first response it is related to the handling of
SIGCHLD.I can give you an overview on how it is supposed to work. Conceptually we want to block and be notified when either a signal occurs (
SIGCHLDa client process terminated,SIGWINCHthe terminal was resized) or I/O is available either from standard input (user keyboard input), a client process, the statusbar FIFO etc.This is realized as follows:
pselectwith an empty signalmask which atomicallySIGCHLD/SIGWINCHwas pending we will now receive itselect, block, if a signal occurs select will return -1 witherrnoset toEINTR(this is crucial, does it happen on Mac OS X?)SIGCHLD/SIGWINCHSee this lwn.net article on why pselect is necessary. However the mentioned race condition should not cause an infinite hang. In the worst case we would block until some other event occurs. For example creating a new window should then remove the old one.
Another thing to investigate is whether the signal handler actually gets called, but for some reason the
diedproperty of the client is not set.When debugging these kind of issues it is extremely useful to get a trace at the syscall layer, as produced by
strace(1)on Linux.Another option is to try to come up with a minimal reproducible test case. How does the following program behave? Run it, then use
kill -WINCH <pid>from another terminal, it should print a message related to the signal. Now pressc<Enter>this should fork a new process and print another message when it dies.