6d5e003446292f20c769c2a32674f9f2f4b41389 — Simon Ser 28 days ago 49bb38d
Handle stopped jobs
M include/shell/job.h => include/shell/job.h +1 -0
@@ 24,6 24,7 @@ void job_destroy(struct mrsh_job *job);
  void job_add_process(struct mrsh_job *job, struct process *proc);
  bool job_terminated(struct mrsh_job *job);
+ bool job_stopped(struct mrsh_job *job);
  void job_set_foreground(struct mrsh_job *job, bool foreground);
  
  bool init_job_child_process(struct mrsh_state *state);

M include/shell/process.h => include/shell/process.h +1 -0
@@ 15,6 15,7 @@ struct process {
  	pid_t pid;
  	struct mrsh_state *state;
+ 	bool stopped;
  	bool terminated;
  	int stat;
  };

M include/shell/task.h => include/shell/task.h +4 -0
@@ 12,6 12,10 @@ * A fatal error occured, the task should be destroyed.
   */
  #define TASK_STATUS_ERROR -2
+ /**
+  * The task has been stopped and the job has been put in the background.
+  */
+ #define TASK_STATUS_STOPPED -3
  
  struct task_interface;
  

M shell/job.c => shell/job.c +10 -0
@@ 127,6 127,16 @@ return true;
  }
  
+ bool job_stopped(struct mrsh_job *job) {
+ 	for (size_t j = 0; j < job->processes.len; ++j) {
+ 		struct process *proc = job->processes.data[j];
+ 		if (!proc->terminated && !proc->stopped) {
+ 			return false;
+ 		}
+ 	}
+ 	return true;
+ }
+ 
  void job_set_foreground(struct mrsh_job *job, bool foreground) {
  	struct mrsh_state *state = job->state;
  

M shell/process.c => shell/process.c +8 -2
@@ 5,6 5,7 @@ #include <string.h>
  #include <sys/wait.h>
  #include "shell/process.h"
+ #include "shell/task.h"
  
  struct process *process_create(struct mrsh_state *state, pid_t pid) {
  	struct process *proc = calloc(1, sizeof(struct process));


@@ 33,9 34,12 @@ }
  
  int process_poll(struct process *proc) {
- 	if (!proc->terminated) {
- 		return -1;
+ 	if (proc->stopped) {
+ 		return TASK_STATUS_STOPPED;
+ 	} else if (!proc->terminated) {
+ 		return TASK_STATUS_WAIT;
  	}
+ 
  	if (WIFEXITED(proc->stat)) {
  		return WEXITSTATUS(proc->stat);
  	} else if (WIFSIGNALED(proc->stat)) {


@@ 62,6 66,8 @@ if (WIFEXITED(stat) || WIFSIGNALED(stat)) {
  		proc->terminated = true;
  		proc->stat = stat;
+ 	} else if (WIFSTOPPED(stat)) {
+ 		proc->stopped = true;
  	} else {
  		assert(false);
  	}

M shell/task/task.c => shell/task/task.c +10 -4
@@ 47,10 47,16 @@ while (true) {
  		int ret = task_poll(task, ctx);
  		if (ret != TASK_STATUS_WAIT) {
- 			ctx->state->last_status = ret;
- 			if (ret != 0
+ 			int status = ret;
+ 			if (ret == TASK_STATUS_STOPPED) {
+ 				status = 148;
+ 			}
+ 			if (ret != TASK_STATUS_ERROR) {
+ 				ctx->state->last_status = status;
+ 				if (status != 0
  					&& (ctx->state->options & MRSH_OPT_ERREXIT)) {
- 				ctx->state->exit = ret;
+ 					ctx->state->exit = status;
+ 				}
  			}
  
  			if (ctx->state->foreground_job != NULL) {


@@ 66,7 72,7 @@   		errno = 0;
  		int stat;
- 		pid_t pid = waitpid(-1, &stat, 0);
+ 		pid_t pid = waitpid(-1, &stat, WUNTRACED);
  		if (pid == -1) {
  			if (errno == EINTR) {
  				continue;