signal handling on background process and file output - c

I have been considering the following code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
FILE* file;
void signal_handler(int _signal) {
switch(_signal){
case SIGTERM:
fprintf(file, "Ouch, the Daemon Child was killed!\n");
fflush(file);
abort();
default:
fprintf(file, "So what?!\n");
fflush(file);
}
}
int main() {
pid_t pid;
int status;
pid = fork();
if(pid != 0) {
// parent
waitpid(pid, &status, WNOHANG); // daemonize the child
} else {
// child
signal(SIGTERM, signal_handler);
file = fopen("daemon.txt", "w");
while(1) {
sleep(1);
fprintf(file, "Daemon child is alive.\n");
fflush(file);
}
}
return 0;
}
and I expected I could find at the end of daemon.txt the string Ouch, the Daemon Child was killed!, after sudo kill -KILL . However, this is not the case. Where is my fault?

You appear to be catching SIGTERM, and then sending SIGKILL, which you do not have a handler for. You will probably see your expected output if you use kill -TERM $pid rather than kill -KILL.

Related

If the subprocess does not call the system call, will the signal sent by kill still take effect?

If the subprocess does not call the system call, will the signal sent by kill still take effect?
It worked. But I want to know when did the subprocess enter the kernel mode.
Code as follows.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
int pid;
if ((pid = fork()) == 0)
{
while (1)
continue;
exit(0);
}
sleep(3);
kill(pid, SIGINT);
int wid, status;
while ((wid = wait(&status)) != -1)
{
printf("child %d: exited with ", wid);
if (WIFEXITED(status))
printf("%d\n", WEXITSTATUS(status));
if (WIFSIGNALED(status))
printf("%d\n", WTERMSIG(status));
}
return 0;
}
Yes, processes that do not make system calls can still receive signals. You can easily test this by writing an infinite loop program, running it, then pressing Ctrl-C, or using the kill command from another terminal window.

In c, linux , about kill and raise

I run my C program on debian-linux ,the program is expected to output
$ ./kill_raise
Child(pid : 4877) is waiting for any signal
Parent kill 4877
but I just got
Parent kill 4877
the string in subprocess (Child(pid : %d) is waiting for any signal) is not print out,why?
and this is my program
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
pid_t pid;
int res;
pid = fork();
if (pid < 0)
{
perror ("Fork error\n");
exit(0);
}
if (pid == 0)
{
printf ("child(pid:%d) is waiting for signal\n", getpid());
raise(SIGSTOP);
exit(0);
}
else
{
if ((waitpid(pid, NULL, WNOHANG)) == 0)
{
if ((res = kill(pid, SIGKILL)) == 0)
{
printf ("parent kill %d\n", pid);
}
}
waitpid(pid, NULL, 0);
exit(0);
}
}
You're hitting a race condition. The parent is executing the kill before the child can execute its printf. Remove WNOHANG so the parent actually waits for the child to stop. Also, you need to add WUNTRACED so that waitpid reports the stop (by default, it will only report termination). Finally, you shouldn't be testing wait()'s return value against 0 in this case.

Signals to child process

I have to write a C program which creates a child and waits for a SIGHUP signal. After receiving that, it sends a signal to it's child. The child executes the default action of the received signal.
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
void sigint();
void sighup();
pid_t pid, pid_parent;
int main(int argc, char const *argv[])
{
if ((pid = fork()) < 0) {
perror("fail1!");
exit(1);
}
else if (pid == 0) {
signal(SIGINT, sigint);
while(1) pause();
exit(1);
}
signal(SIGHUP, sighup);
printf("PARENT's pid: %d\n", pid_parent = getpid());
while(1) pause();
return 0;
}
void sighup()
{
signal(SIGHUP,sighup);
kill(pid,SIGINT);
printf("PARENT(%d): I received a SIGHUP. I'll send something to my child(%d).\n",getpid(),pid);
printf("OK");
}
void sigint()
{
signal(SIGINT,sigint);
printf("CHILD: I received a SIGINT. I'll execute it.");
signal(SIGINT,SIG_DFL);
}
Seems like it doesn't work after kill(pid, SIGQUIT). And I really don't have ideas why.

child-process signal handling in c

I need your help in an exercise i have about signal handling between processes. I think that it's a trivial question but i can't find the answer anywhere. I want to print something from the parent in a file, send a signal from the parent to the child, the child has to print in a file and then send a signal from the child to the parent.
The code i am using is this:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#define WRITEF 123451 //Random number
FILE *infile;
void writef() {
fprintf(infile, "Child Starting (%d)\n", getpid());
printf("Child Starting (%d)\n", getpid());
}
int main() {
pid_t pid;
infile = fopen("pid_log.txt","w");
pid = fork();
signal(WRITEF, writef);
if ( pid == 0 ) {
pause();
printf("enter child\n");
}
else {
fprintf(infile, "Parent (%d)\n", getpid());
printf("Parent (%d)\n", getpid());
kill(pid, WRITEF);
pause();
wait((int*)1);
}
fclose(infile);
return 1;
}
PROBLEM SOLVED!!!
The key is that you have to register the signal (use the singal function) before every pause(). Also you cannot use a "user-made" signal and in my case i used SIGCONT.
Here is the final (almost) version of my program:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
FILE *infile;
void noth() {
}
void writec() {
infile = fopen("pid_log.txt","a+");
fprintf(infile, "Child (%d)\n", getpid());
printf("Child (%d)\n", getpid());
fclose(infile);
}
void writep() {
infile = fopen("pid_log.txt","a+");
fprintf(infile, "Parent (%d)\n", getpid());
printf("Parent (%d)\n", getpid());
fclose(infile);
}
main() {
pid_t pid = fork();
if ( pid == 0 ) { //child process
signal(SIGCONT,noth); //registering signal before pause()
pause();
infile = fopen("pid_log.txt","a+");
printf("Child Starting (%d)\n",getpid());
fprintf(infile,"Child Starting (%d)\n",getpid());
fclose(infile);
while (1) {
sleep(2);
kill(getppid(), SIGCONT); //sending singal to parent
signal(SIGCONT, writec);
pause();
}
}
else { //parent process
infile = fopen("pid_log.txt","a+");
printf("Parent Starting (%d)\n",getpid());
fprintf(infile,"Parent Starting (%d)\n",getpid());
fclose(infile);
kill(pid, SIGCONT);
signal(SIGCONT, writep);
pause();
while (1) {
sleep(2);
kill(pid, SIGCONT);
signal(SIGCONT, writep);
pause();
}
}
return 1;
}

Father process was block while set SIGCHLD

This is my code, I had simplified it.
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
void signal_handle(int sig)
{
int status;
wait(&status);
}
int main()
{
pid_t pid = fork();
if (pid > 0)
signal(SIGCHLD, signal_handle);
if (pid == 0) {
if (execl("/bin/ls", "/", (char *)0) < 0)
{
perror("execl");
return -1;
}
}
return 0;
}
When I run it, I found that, son process print the run result, but father process
was blocked.
what should I do, if a father has much son process? set wait(&status) for every one?
I'm very sorry for my bad english!
I don't see why the parent process would hang, and it doesn't on my machine.
After the fork(), the parent process invokes signal() to set the signal handler and immediately exits. The child, meanwhile, executes ls to print the contents of the current directory (because the "/" argument becomes argv[0], the program name, and there are no additional arguments). It then exits too. Except under very unlikely circumstances, the parent has exited long before the child completes.
If you want the parent process to wait until it gets the 'death of a child' signal, add a call to pause() in the parent-only execution path:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
static void signal_handle(int sig)
{
int status;
pid_t pid = wait(&status);
printf("%d: signal %d child %d status 0x%.4X\n", (int)getpid(), sig, (int)pid, status);
}
int main(void)
{
pid_t pid = fork();
if (pid > 0)
{
signal(SIGCHLD, signal_handle);
pause();
}
else if (pid == 0)
{
execl("/bin/ls", "ls", "/", (char *)0);
perror("execl");
return -1;
}
else
perror("fork");
return 0;
}

Resources