Currently I'm making a shell and it works fine for the foreground processes that it executes. Now I have to implement background processes and job control and I am honestly confused on how I should approach it. I understand that if I want to run the proccesses in the background, I should set their pgid and simply not wait for them, however I have hit a wall when trying to reap them...
I have two structs: job and process
typedef struct job {
int is_background_job;
pid_t pgid;
int job_status;
process *p; // List of processes to execute for this job
struct job *next; // If a background job, it will be in a global linked list of job structs
} job;
typedef struct process {
char **argv;
process *next; // The next process to pipe to
} process;
The important part is that a job consists of a linked list of process structs and that there is a global list of job structs which represents all of my background jobs going on.
The shell algorithm is kind of standard.
shell:
get cmd from terminal
parse cmd and create a job struct filled with processes
if job is a background job:
add it to global background job list
fork(), setpgid, and do the piping in a while loop of the job's processes
if job is a foreground process:
wait on the forked processes
else:
don't wait // since it's a background process
continue to loop and read next cmd from terminal
Now here's my issue. If I have a bunch of processes that are being executed in the background, that means any one of them (from any one of the background jobs) could simply end and then send SIGCHLD. The annoying part is that if all processes for a certain job end, I have to remove that job from the global jobs list. I don't think I can call a loop of waitpid(-1, &status, WNOHANG) in my SIGCHLD handler here because on the off chance that the forground process currently executing finsihes while in the signal handler.
Does this mean I have to go through and waitpid() on every process of every job as soon as a get a SIGCHLD so that I only wait on non-fg processes?
I don't really need code, just an explanation on a good way to do this.
sigactionand after the isr you can handle the other processes signal handler - Anjaneyulu