I have a C program that uses forkpty to execute a bash shell. I'm finding that the programs launched by this shell are launched with SIGINT ignored, so when I send a Ctrl-C to the shell they never close.
example:
int masterFd;
char* args[] = {"/bin/bash", "-i", NULL };
int procId = forkpty(&masterFd, NULL, NULL, NULL);
if( procId == 0 ){
execve( args[0], args, NULL);
}
else {
// Simple code that reads from standard in and writes to masterFd.
// I also register for Ctrl-C and write it to masterFd if caught
}
Other control characters seem to make it through, ctrl-D, ctrl-? etc. However, whenever I look at the status of a process launched by the new bash shell it appears as if SIGINT is masked out.
MyShell:# sleep 1000
StandardTerm:# ps -ef | grep sleep
root 26611 19278 0 17:44 pts/1 00:00:00 sleep 1000
root 26613 32376 0 17:44 pts/1 00:00:00 grep sleep
StandardTerm:# grep Sig proc/26611/status
SigQ: 0/256428
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000010006 <- THE 6 IS THE PROBLEM
SigCgt: 0000000180000000
SigIgn has the 2 bit set, which means 2 (SIGINT) is ignored. if I do the exact same thing, but run sleep (or cat a giant file or whatever) in a standard terminal, this bit is cleared. What am I doing when I launch my pty bash that is causing it to create grandchildren programs with SIGINT ignored?
Moreover, if I send a SIGINT signal to the process
StandardTerm:# kill -2 26611
nothing happens. What's strange is when I send the same command to the bash shell I forkpty'ed IT works, because that bash shell is not ignoring SIGINT.
Best Answer
This outcome cannot be due to the code block you showed in your question. There must be something else in other parts of your overall setup.
Given only the usage scenario you described, the most likely reason is that you actually set SIGINT to be ignored in your code somewhere before the forkpty, or before the execve in forkpty’s child.
This would yield the outcome you describe because then your forkpty’ed
bash -i
would inherit such SIGINT-ignored setup, and while it would set it otherwise for its own internal purposes (thus not ignoring SIGINT) it would also reset it to the inherited ignored state for each and every command it would spawn.This is documented Bash’s behavior, see Bash’s man-page at “COMMAND EXECUTION ENVIRONMENT” chapter, specifically the paragraph saying:
HTH