First off, sorry that I was not able to provide a reduced example. At the moment, it was beyond my ability. Especially my codes that pass the file descriptors around wasn't cleanly working. I think I have only a fair understanding on how the code works at a high level.
The question is essentially if, in the following complicated example, the end-user enters Ctrl + C
, which process takes the SIGINT
and how things happen that way.
The application works on the Command Line Interface (CLI, going forward). The user starts a client, which effectively sends a command to the server, prints some responses out, and terminates. The server upon request finds a proper worker executable, and fork-and-exec
the executable, and waits for it. Then, the server constructs the response and sends it back to the client.
There are, however, some complications. The client starts the server if the server process is not already running -- there's one server process per user. When the server is fork-and-exec
'ed, the line just after fork()
has this:
if (pid == 0) {
daemon(0, 0);
// do more set up and exec
}
Another complication, which might be more important,is that when the client sends a request over a unix socket (which looks like @server_name
), the client appears to send the three file descriptors for standard I/O, using techniques like this.
When the server fork-and-exec
s the worker executable, the server redirects the worker's standard I/O to the the three file descriptors received from the client:
// just after fork(), in the child process' code
auto new_fd = fcntl(received_fd, F_DUPFD_CLOEXEC, 3);
dup2(new_fd, channel); // channel seems to be 0, 1, or 2
That piece of codes run for all the three file descriptors, respectively. (The worker executable yet again creates a bunch of processes but it does not pass the STDIN
to its children.)
The question is what happens if the end user inputs Ctrl + C
in the terminal. I thought, the Bash
shell takes it, and generates & sends SIGINT
to the processes that has a particular session ID perhaps same as the bash shell's direct child process or itself: the client, in the example.
However, it looks like the worker executable receives the signal, and I cannot confirm if the client receives the signal. I do not think the server process receives the signal but cannot confirm that. How could this happen?
If the Bash
takes the Ctrl+C
first, and delivers it to whatever processes, I thought the server has been detached from the Bash
(i.e. daemon(0, 0)
), and has nothing to do with the bash process. I thought the server and thus the worker processes have different session IDs, and which looked so when I ran the ps -o
command.
It's understandable that the user keyboard inputs (yes
or no
, etc) could be delivered to the worker process. I am not sure how Ctrl + C
could be delivered to the worker process by just effectively sharing the standard input. I would like to understand how it works.
%P.S.Thank you for the answers and comments! The answer was really helpful. It sounded like the client must get the signal, and the worker process must be stopped by other mechanism. Based on that, I could look into the code deeper. It turned out that the client indeed catches the signal and dies. It breaks the socket connection. The server detects when the fd is broken, and signals the corresponding worker process. That was why the worker process looked like getting the signal from the terminal.
It's not Bash that sends the signal, but the tty driver. It sends it to the foreground process group, meaning all processes in the foreground group receive it.