Unix and Signal Handlers (C) - c

I'm a student and I am trying to understand signals within a course about Unix programming.
To start, I wanted to test a simple example: a process makes a child and needs a confirmation of the actual creation.
I fork, and within the child I send a SIGUSR1 to the father with
kill(getppid(), SIGUSR1);
Then, within the father, I wrote a pause(); sys call to block the process until a signal is received, and then I wrote the
(sigaction(SIGUSR1, &sa, NULL) check.
Problem is, the signal is sent and the program stops, with no handler execution.
I compile it with
$gcc -Wall -o test test.c
I get no warnings, and the output is
$I am the father
$I am the child
$User defined signal 1
I know I could do this in other ways (with sleep sys call, etc.), but I just want to understand why this code doesn't work.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void new_child (int sig){
write(1,"I made a new child\n",50);
}
int main(){
pid_t child;
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = new_child;
switch(child = fork()){
case -1:
printf("Error.\n");
exit(EXIT_FAILURE);
case 0:
printf("I am the child\n");
kill(getppid(), SIGUSR1);
break;
default:
printf("I am the father\n");
pause();
if (sigaction(SIGUSR1, &sa, NULL) == -1){
printf("Signal error.\n");
exit(EXIT_FAILURE);
}
printf("I'm done.");
kill (child, SIGKILL);
exit(EXIT_SUCCESS);
}
}
I know this question has already been asked, but I cannot seem to find a solution that works in my case.

You must change the signal at the beginning of the code so that it can execute as soon as SIGUSR is received – Anjaneyulu
"You must change the signal at the beginning of the code ..." this restriction is a bit tight. The signal handler needs to be install latest just before calling fork().
– alk

Related

Keeping parent process alive while child process will be terminated by SIGINT signal

As I dig deep into SIGNAL in c, I was wondering is it possible to keep parent process alive upon receiving SIGINT signal but I got a bit confused researching online as they isn't much discussion about it.
Is it possible to use signal handler to keep parent process alive by ignoring the SIGINT signal for parent process.
If yes, how should I implement it?
I would say, that there is nothing to discuss.
Have a look at the man page of signal(7). In the section Standard signals, the default action for SIGINT is program termination. That means, if you do not handle the specified signal, the kernel takes the default action, therefore, if you want to keep the process alive, you have to catch the signal.
To answer your question, read the provided man page.
A process can change the disposition of a signal using sigaction(2) or signal(2).
#Erdal Küçük has already answered your question but here is a sample piece of code so you can understand it better.
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void handler(int _) {
(void)_;
printf("\nEnter a number: ");
ffush(stdout);
}
int main(void) {
pid_t pid;
pid = fork();
int n = 0;
if (pid < 0) {
perror("Can't fork");
} else if (pid == 0) {
// Child process
kill(getpid(), SIGKILL); // Killing the child process as we don't need it
} else {
// Parent process
struct sigaction sg;
sg.sa_flags = SA_RESTART;
sg.sa_handler = handler;
sigaction(SIGINT, &sg, NULL);
printf("Enter a number: ");
scanf("%d", &n);
}
printf("Value of n = %d", n);
return 0;
}

Treating signals correctly inside system()

I have been reading "The Linux Programming Interface". Chapter 27, Program execution.
I understand that the author demonstrates how we could implement the system call using exec and fork. However, the challenging part is handling signals. In particular I am confused with the following text
The first signal to consider is SIGCHLD. Suppose that the program
calling system() is also directly creating children, and has
established a handler for SIGCHLD that performs its own wait(). In
this situation, when a SIGCHLD signal is generated by the termination
of the child created by system(), it is possible that the signal
handler of the main program will be invoked and collect the child’s
status before system() has a chance to call waitpid(). (This is an
example of a race condition.)
The following is the code example without signal handling
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
int system(char *command)
{
int status;
pid_t childPid;
switch(childPid = fork())
{
case -1: /* Error */
return -1;
case 0: /* Child */
execl("/bin/sh", "sh", "-c", command, (char*) NULL);
_exit(127); /* If reached this line than execl failed*/
default: /* Parent */
if (waitpid(childPid), &status, 0) == -1)
return -1;
else
return status;
}
}
I know what the race condition ism but don't understand the whole scenario the author describes. In particular, I don't understand what "the program calling system" might be. What is the "main program"? Which process creates child procs?
Could someone, please, explain by giving examples how a race condition can arise? In C or in pseudocode.
You could have a SIGCHLD handler installed that does int ws; wait(&ws);.
If such a SIGCHLD handler is allowed to run in response to a SIGCHLD, it will race with the waitpid done in system, preventing system from successfully retrieving the exit status of the child if the handler wins the race.
For this reason, POSIX prescribes that SIGCHLD be blocked in system.
You could still have races with wait calls done in other signal handlers or other threads, but that would be a design error that POSIX system won't help you with.
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
int system(char *command)
{
int status;
pid_t childPid;
switch(childPid = fork())
{
case -1: /* Error */
return -1;
case 0: /* Child */
execl("/bin/sh", "sh", "-c", command, (char*) NULL);
_exit(127); /* If reached this line than execl failed*/
default: /* Parent */
/*usleep(1);*/
if (waitpid(childPid, &status, 0) == -1)
return -1;
else
return status;
}
}
void sigchld(int Sig){ int er=errno; wait(0); errno=er; }
int main()
{
/*main program*/
//main program has a sigchld handler
struct sigaction sa;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sa.sa_handler = sigchld;
sigaction(SIGCHLD, &sa,0);
for(;;){
//the handler may occasionally steal the child status
if(0>system("true") && errno==ECHILD)
puts("Child status stolen!");
}
}

How to set the paused process to background?

I am new in C. I am trying to make a shell - like program. I am currently making a signal handler, which means, when the process is running and somebody pressed ctrl + Z the process should pause and go to background while shell has to continue. The problem here is: parent process is making wait(NULL), but child is not ending the program so basically parent waits the child which is not ending the program yet. How to make it so that parent continues to work foreground. (you can see my code How to redirect signal to child process from parent process? here)
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
pid_t pid;
void send_signal(int signum){
kill(pid, signum);
}
void init_signals(){
signal(SIGINT, send_signal);
signal(SIGTSTP, send_signal);
}
int main(){
init_signals();
pid = fork();
if(pid > 0){
//Parent Process
printf("PARENT: %d\n", getpid());
waitpid(pid, NULL, WUNTRACED);
printf("Parent out of wait, i think this is what you are expecting\n");
} else {
struct sigaction act = {{0}};
act.sa_handler = send_signal;
act.sa_flags = SA_RESETHAND;
sigaction(SIGTSTP, &act, NULL);
sigaction(SIGINT, &act, NULL);
perror("sigaction ");
printf("CHILD: %d\n", getpid());
// Child Process
while(1){
usleep(300000);
}
}
return 0;
}
I think above code can serve your purpose. Let me explain it.
In your code [How to redirect signal to child process from parent process? you have handled signal and from hander context sending same signal.When you pressed Ctrl + c or Ctrl + z both parent and child receives signal. Now as per the handler code
void send_signal(int signum) {
kill(pid, signum);
}
when handler will execute in parent's context pid will be equal to child's pid so it will send signal to child but when handler runs in child context pid value will be 0, so it sends signal to whole process group i.e. parent as well as child. this make you code to run handler recursively for infinite times. Due to this you are not getting desired result.
I have modified two things to get desired result.
child context
In child context restore the signal action to the default upon entry to the signal handler so that when child receives signal for second time signal default action can be performed.
parent context
use waitpid() instead of wait().
pid_t waitpid(pid_t pid, int *status, int options);
The waitpid() system call suspends execution of the calling process until a child specified by pid argument has changed state. By default, waitpid() waits only for terminated children, but this behavior is modifiable via the options argument.
`WUNTRACED` also return if a child has stopped
Due to WUNTRACED parent process will return when child will be stopped or terminated.
I hope it will serve you purpose ask me if it don't.

Signal handling in C

I am figuring how signals work in C.
Here is one of the examples taken from old exams:
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<errno.h>
//#include <sys/types.h>
void handler1(int sig) {
printf("Phantom");
exit(0);
}
int main()
{
pid_t pid1;
signal(SIGUSR1, handler1); //installing signal handler
if((pid1 = fork()) == 0) { //forking
printf("Ghost");
exit(0);
}
kill(pid1, SIGUSR1);
printf("Ninja");
return 0;
}
So far, GCC gives me two answers Ghost Ninja & Ninja Phantom. Could it produce Ghost Phantom Ninja or any other combination made of 3 names ?
One way I see it could possibly produce 3 names is:
Fork, run in Child, print Ghost, exit(0) => in Parent, accept/process signal and from signal Handler print Phantom, kill child, print Ninja. But I am not sure if my "theory" holds the ground.
Also, would the kill(pid1, SIGUSR1) invoke handler() ?
Thanks !
Let's examine this line-by line. Set up a signal handler, then fork. The child prints "Ghost" and exits. The parent makes the child print "Phantom" and exit. Then the parent prints "Ninja".
So you've really got a race condition. If the parent fires its SIGUSR1 before the child prints "Ghost", then you'll get Phantom Ninja, or perhaps Ninja Phantom (does kill block?)
But, if you can't get the signal off in time, then you'll get Ghost Ninja as the child finishes before the parent signals. I don't think the reverse is possible.
Now it is conceivable that the signal could be exactly on time to hit between the printf and the exit, in which case Ghost would finish, followed by Phantom then Ninja - or the reverse again, I think.
It's really finicky and sensitive to OS timing.
#Everyone - not tested! Feel free to contradict me, but I'll be as interested to know why as the OP.
Lets mark the lines with line numbers first as follows:
signal(SIGUSR1, handler1); //installing signal handler ---- 1
if((pid1 = fork()) == 0) { //forking ---- 2
printf("Ghost"); ---- 3
exit(0); ---- 4
}
kill(pid1, SIGUSR1); ---- 5
printf("Ninja"); ---- 6
Now with the above code, if
Child executes first and
if 3 is executed first, then child is suspended and parent starts executing with 5. This will print GhostPhantomNinja
However, a definite order can not be determined.
You have two non deterministic factors here, which are both depends on the OS: when will the context switching occur, and when will the signal arrive.
Since you can't control those, I'd answer that any order is possible. Try inserting wait() between command and see if you get the desired results.
//#include <sys/types.h>
#include<stdlib.h>
void handler1(int sig) {
printf("Phantom\n");
waitpid(-1,NULL,0);
//sexit(0);
}
int main()
{
pid_t pid1;
signal(SIGUSR1, handler1); //installing signal handler
printf("my pid is %d ha ha parent..\n",getpid());
//if((pid1 = fork()) == 0) { //forking
pid1=fork();
if(pid1==0)//in childe processs
{
printf("my pid is %d ha ha child..\n",getpid());
printf("Ghost\n");
sleep(6);
exit(0);
}
else{
//sleep(4);
kill(pid1, SIGUSR1);
sleep(3);
printf("Ninja\n");
return 0;
}
}

Test cases in C for WIFSIGNALED, WIFSTOPPED, WIFCONTINUED

I'm playing with waitpid() and signal() and I'm looking for reliable test cases for returning WIFSIGNALED(status) = WIFSTOPPED(status) = WIFCONTINUED (status) = true but can't find any...
Care to tell me how can I make sure those return true so I can debug my code?
Also, a few hints about what signals should I catch with signal() to test those macros would be helpful...
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#define NELEMS(x) (sizeof (x) / sizeof (x)[0])
static void testsignaled(void) {
kill(getpid(), SIGINT);
}
static void teststopped(void) {
kill(getpid(), SIGSTOP);
}
static void testcontinued(void) {
kill(getpid(), SIGSTOP);
/* Busy-work to keep us from exiting before the parent waits.
* This is a race.
*/
alarm(1);
while(1) {}
}
int main(void) {
void (*test[])(void) = {testsignaled, teststopped, testcontinued};
pid_t pid[NELEMS(test)];
int i, status;
for(i = 0; i < sizeof test / sizeof test[0]; ++i) {
pid[i] = fork();
if(0 == pid[i]) {
test[i]();
return 0;
}
}
/* Pause to let the child processes to do their thing.
* This is a race.
*/
sleep(1);
/* Observe the stoppage of the third process and continue it. */
wait4(pid[2], &status, WUNTRACED, 0);
kill(pid[2], SIGCONT);
/* Wait for the child processes. */
for(i = 0; i < NELEMS(test); ++i) {
wait4(pid[i], &status, WCONTINUED | WUNTRACED, 0);
printf("%d%s%s%s\n", i, WIFCONTINUED(status) ? " CONTINUED" : "", WIFSIGNALED(status) ? " SIGNALED" : "", WIFSTOPPED(status) ? " STOPPED" : "");
}
return 0;
}
Handling WIFSIGNALED is easy. The child process can commit suicide with the kill() system call. You can also check for core dumps - some signals create them (SIGQUIT, IIRC); some signals do not (SIGINT).
Handling WIFSTOPPED may be harder. The simple step to try is for the child to send itself SIGSTOP with the kill() system call again. Actually, I think that should work. Note that you may want to check on SIGTTIN and SIGTTOU and SIGTSTOP - I believe they count for WIFSTOPPED. (There's also a chance that SIGSTOP only works sanely when sent by a debugger to a process it is running via the non-POSIX system call, ptrace().)
Handling WIFCONTINUED is something that I think the parent has to do; after you detect a process has been stopped, your calling code should make it continue by sending it a SIGCONT signal (kill() again). The child can't deliver this itself; it has been stopped. Again, I'm not sure whether there are extra wrinkles to worry about - probably.
A framework something like the below will allow you check the results of the wait() and waitpid() calls.
pid_t pid = fork();
if (pid == 0) {
/* child */
sleep(200);
}
else {
/* parent */
kill(pid, SIGSTOP);
/* do wait(), waitpid() stuff */
}
You do not actually have to catch the signals (using signal() or related function) that are sent. signal() installs a handler that overrides the default behavior for the specific signal - so if you want to check for a signal terminating your process, pick one that has that default behavior - "man -s7 signal" will give you details a signal's default behavior.
For the macros you have mentioned use SIGSTOP for WIFSTOPPED(status), SIGCONT for WIFCONTINUED (status) and SIGINT for WIFSIGNALED(status)
If you want more flexibility for testing, you could use kill (see "man kill") to send signals to your process. kill -l will list all the signals that can be sent.
in your tests you can fork() and send specific signal to your child processes? In this scenario your child processes are test cases?
EDIT
my answer is about coding a C test. you fork, get the pid of your child process (the process
with signal handlers installed), then you can send signal to it by using kill(2).
In this way you can test the exit status

Resources