process - How to properly wait for foreground/background processes in my own shell in C? -
in this previous question posted of own shell code. next step implement foreground , background process execution , wait them terminate don't stay "zombies".
before adding possibility run them in background, processes running in foreground. , that, called wait(null) after executing process execvp(). now, check '&' character last argument , if it's there, run process in background not calling wait(null) , process can run happily in background i'm returned shell.
this working (i think), problem now, need call wait() (or waitpid() ?) somehow background process doesn't remain "zombie". that's problem, i'm not sure how that...
i believe have handle sigchld , there, have yet understand when sigchld signal sent because tried add wait(null) childsignalhandler() didn't work because executed process in background, childsignalhandler() function called , consequently, wait(null), meaning couldn't shell until "background" process finished. wasn't running on background anymore because of wait in signal handler.
what missing in this?
one last thing, part of exercise need print changes of processes status, process termination. so, insight on appreciated.
this full code @ moment:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <wait.h> #include <signal.h> #include <sys/types.h> #include "data.h" // boolean typedef , true/false macros void childsignalhandler(int signum) { // } int main(int argc, char **argv) { char bbuffer[bufsiz], *pargs[10], *aptr = null, *sptr; bool background; ssize_t rbytes; int acount; pid_t pid; //signal(sigint, sig_ign); signal(sigchld, childsignalhandler); while(1) { write(1, "\e[1;31mmybash \e[1;32m# \e[0m", 27); rbytes = read(0, bbuffer, bufsiz-1); if(rbytes == -1) { perror("read"); exit(1); } bbuffer[rbytes-1] = '\0'; if(!strcasecmp(bbuffer, "exit")) { exit(0); } sptr = bbuffer; acount = 0; { aptr = strsep(&sptr, " "); pargs[acount++] = aptr; } while(aptr); background = false; if(!strcmp(pargs[acount-2], "&")) { pargs[acount-2] = null; background = true; } if(strlen(pargs[0]) > 1) { pid = fork(); if(pid == -1) { perror("fork"); exit(1); } if(pid == 0) { execvp(pargs[0], pargs); exit(0); } if(!background) { wait(null); } } } return 0; }
there various options waitpid()
(quotes posix standard):
wcontinued
the waitpid() function shall report status of continued child process specified pid status has not been reported since continued job control stop.
wnohang
the waitpid() function shall not suspend execution of calling thread if status not available 1 of child processes specified pid.
in particular, wnohang allow see whether there corpses collect without causing process block waiting corpse.
if calling process has sa_nocldwait set or has sigchld set sig_ign, , process has no unwaited-for children transformed zombie processes, calling thread shall block until of children of process containing calling thread terminate, , wait() , waitpid() shall fail , set errno [echild].
you don't want ignoring sigchld, etc, , signal handler should setting flag tell main loop "oops; there's dead child - go collect corpse!".
the sigcont , sigstop signals of relevance - used restart , stop child process, respectively (in context, @ rate).
i'd recommend looking @ rochkind's book or stevens' book - cover these issues in detail.
Comments
Post a Comment