c - Hanging loop with sleep() -
i'm trying learn how handle signals. in program have array of pids of earlier created subprocesess. no want every couple seconds send sigtstp signal 1 of them. have send sigchld parent process , exit. parent process should print exit code of exited process , create next 1 in place of exit one. works fine in first loop hangs in second. on output get:
loop slept forking in array loop zakonczyl sie potomek 3934 z kodem 0.
so it's seems sleep works in first loop not in second. or main process didn't control after handling signal should't happen. have no idea whats may wrong here.
while(1) { printf("loop\n"); sleep(5); printf("slept\n"); int r = rand() % n; if(kill(process_tab[r],sigtstp) < 0) { printf("error while sending sigtstp signal.\n"); } else { printf("forking\n"); if((child = fork()) < 0) { printf("fork failed.\n"); } else if(child == 0) {//to sie dzieje w procesie if(signal(sigtstp,&catch_sigtstp)) { printf("error while setting signal handler.\n"); _exit(exit_failure); } while(1) { } } else { //to sie dzieje w parencie process_tab[r] = child; printf("in array\n"); } } }
and here handlers.
void catch_sigtstp(int signal) { kill(ppid,sigchld); _exit(exit_success); } void catch_sigchld (int signal) { int status; pid_t child = wait(&status); printf("zakonczyl sie potomek %d z kodem %d.\n",child,status); }
add fflush
after printf
.
printf("something\n"); fflush(stdout);
otherwise may not output stdio
buffered default.
edit: issues of handler
it pretty unsafe use printf
function in signal handler, not reentrant. also, catch_sigchild
function can modified:
void catch_sigchld (int signal) { int status; pid_t child; while ((child = waitpid(-1, &status, wnohang)) > 0) { // may else? // ...printf("zakonczyl sie potomek %d z kodem %d.\n",child,status); } }
the reason 1 signal can delivered multiple dead children.
edit: blocking signal when printing.
to avoid deadlock inside stdio, should block signal:
sigset_t set; sigemptyset(&set); sigaddset(&set, sigchild); ... sigprocmask(sig_block, &set, null); printf("my output"); sigprocmask(sig_unblock, &set, null); ...
edit: @barmar has pointed, parent process receive sigchild signal twice: once child'd signal handler, , 1 os.
to fix, might sufficient remove own signal source:
void catch_sigtstp(int signal) { // kill(ppid,sigchld); //< 1 causes 2 signals per 1 child _exit(exit_success); }
Comments
Post a Comment