Help debugging my program

#1

Hey all,

I’ve been working on Dingus in my free time. I use it daily to load up configuration files full of environment variables to streamline my development process. It just loads a YAML file into a HashMap and loads those into a std::process::Command that is whatever program $SHELL is (in my case it’s the Fish shell).

Lately I’ve noticed panes in TMUX dying after navigating around a bit, each of these panes that die have all been running dingus. I’ve only noticed this as recently, so I’m not sure if this has always been a thing or what - but luckily I’ve found how to reproduce the issue: Tab complete and hit control-C to close Tab completion.

Every time I do that, dingus dies, then the parent process that spawned the dingus subshell. I don’t know a whole lot about systems level programming, but I believe this is happening because SIGINT is being propagated upwards into the parent process. Why this is happening, I have no idea - but some googling leads me to believe that it would be worth trying to set setgpid. The std::process::Command builder unfortunately doesn’t allow for child processes with a differing gpid to be spawned, however, so I’m not sure how to proceed.

I think I’d like to find out how to verify that this is indeed what is happening, although I have no idea how. If it is, I’d like to figure out how to properly spawn my subshell in a manner that the child process dying due to a SIGINT won’t kill the parent. It’s annoying :stuck_out_tongue:

Any help at all would be awesome - thanks to the community for getting me into this mess :smiley:

1 Like
#2

Also look into SIGCHLD. You can run your process with strace -f -e trace=execve [CMD] to see which signals are being sent. Maybe you should be ignoring some of the signals? You can use the libc or nix crates to setup signal handlers.

#3

That’s super helpful - sadly I don’t have strace available to me, but I do have dtrace available. I have no idea how to use either though, so this is definitely a rabbit hole :slight_smile:. It’ll be fun to go down, though - thanks for the direction!

#4

You need to do some reading about the POSIX tty model and process groups.

When you press Ctrl-C, the kernel sends a SIGINT to the processes that are in the terminal’s “foreground process group”. It sounds to me like when you start your subshell you should be starting it in a new process group.

Edit: some good discussion and explanations in the following:

1 Like
#5

That makes a lot of sense - I guess my only question then is how to create a new process group that doesn’t collide with existing process groups.

#7

after you fork, in the child call the setpgrp(0, 0) syscall (via some wrapper in the appropriate -sys crate) before then exec’ing the shell. That will set the pgrp of the child to its own pid. That is what the shell does when starting a sub-command, and is in turn why killing one of those commands with ^C isn’t triggering your problem - only ^C’s when the shell itself is in the foreground.

It may be that you need to bypass some of the convenience process builder mechanisms (or find a different one) that lets you get enough control between these steps.

#8

@jethrogb @dcarosone, thanks for your help!