~emersion/mrsh

63b24336f850e31d6c622291fa4238b5d8c03732 — Simon Ser 2 years ago 1e83638
Fix signalled process exit code, finished → terminated
M include/shell/job.h => include/shell/job.h +2 -2
@@ 24,7 24,7 @@ void job_destroy(struct mrsh_job *job);
void job_add_process(struct mrsh_job *job, struct process *proc);
bool job_finished(struct mrsh_job *job);

bool job_init_process(struct mrsh_state *state);
void job_notify(struct mrsh_state *state, pid_t pid, int stat);
bool init_job_child_process(struct mrsh_state *state);
void update_job(struct mrsh_state *state, pid_t pid, int stat);

#endif

M include/shell/process.h => include/shell/process.h +3 -3
@@ 9,13 9,13 @@
 * This struct is used to track child processes.
 *
 * This object is guaranteed to be valid until either:
 * - The process exits
 * - The process terminates
 * - The shell is destroyed
 */
struct process {
	pid_t pid;
	struct mrsh_state *state;
	bool finished;
	bool terminated;
	int stat;
};



@@ 23,6 23,6 @@ struct process *process_create(struct mrsh_state *state, pid_t pid);
void process_destroy(struct process *process);
int process_poll(struct process *process);

void process_notify(struct mrsh_state *state, pid_t pid, int stat);
void update_process(struct mrsh_state *state, pid_t pid, int stat);

#endif

M shell/job.c => shell/job.c +20 -20
@@ 75,23 75,6 @@ bool mrsh_set_job_control(struct mrsh_state *state, bool enabled) {
	return true;
}

bool job_init_process(struct mrsh_state *state) {
	if (!state->job_control) {
		return true;
	}

	struct sigaction sa = { .sa_handler = SIG_DFL };
	sigemptyset(&sa.sa_mask);
	for (size_t i = 0; i < IGNORED_SIGNALS_LEN; ++i) {
		if (sigaction(ignored_signals[i], &sa, NULL) != 0) {
			fprintf(stderr, "sigaction failed: %s\n", strerror(errno));
			return false;
		}
	}

	return true;
}

static void array_remove(struct mrsh_array *array, size_t i) {
	memmove(&array->data[i], &array->data[i + 1],
		(array->len - i - 1) * sizeof(void *));


@@ 133,13 116,30 @@ void job_add_process(struct mrsh_job *job, struct process *proc) {
bool job_finished(struct mrsh_job *job) {
	for (size_t j = 0; j < job->processes.len; ++j) {
		struct process *proc = job->processes.data[j];
		if (!proc->finished) {
		if (!proc->terminated) {
			return false;
		}
	}
	return true;
}

void job_notify(struct mrsh_state *state, pid_t pid, int stat) {
	process_notify(state, pid, stat);
bool init_job_child_process(struct mrsh_state *state) {
	if (!state->job_control) {
		return true;
	}

	struct sigaction sa = { .sa_handler = SIG_DFL };
	sigemptyset(&sa.sa_mask);
	for (size_t i = 0; i < IGNORED_SIGNALS_LEN; ++i) {
		if (sigaction(ignored_signals[i], &sa, NULL) != 0) {
			fprintf(stderr, "sigaction failed: %s\n", strerror(errno));
			return false;
		}
	}

	return true;
}

void update_job(struct mrsh_state *state, pid_t pid, int stat) {
	update_process(state, pid, stat);
}

M shell/process.c => shell/process.c +10 -4
@@ 33,13 33,19 @@ void process_destroy(struct process *proc) {
}

int process_poll(struct process *proc) {
	if (!proc->finished) {
	if (!proc->terminated) {
		return -1;
	}
	return WEXITSTATUS(proc->stat);
	if (WIFEXITED(proc->stat)) {
		return WEXITSTATUS(proc->stat);
	} else if (WIFSIGNALED(proc->stat)) {
		return 129; // POSIX requires >128
	} else {
		assert(false);
	}
}

void process_notify(struct mrsh_state *state, pid_t pid, int stat) {
void update_process(struct mrsh_state *state, pid_t pid, int stat) {
	struct process *proc = NULL;
	bool found = false;
	for (size_t i = 0; i < state->processes.len; ++i) {


@@ 54,7 60,7 @@ void process_notify(struct mrsh_state *state, pid_t pid, int stat) {
	}

	if (WIFEXITED(stat) || WIFSIGNALED(stat)) {
		proc->finished = true;
		proc->terminated = true;
		proc->stat = stat;
	} else {
		assert(false);

M shell/task/command_process.c => shell/task/command_process.c +1 -1
@@ 42,7 42,7 @@ static bool task_process_start(struct task_command *tc, struct context *ctx) {
		return false;
	} else if (pid == 0) {
		put_into_process_group(ctx, getpid());
		job_init_process(ctx->state);
		init_job_child_process(ctx->state);
		// TODO: give the terminal to the process group, if foreground job

		for (size_t i = 0; i < sc->assignments.len; ++i) {

M shell/task/task.c => shell/task/task.c +1 -1
@@ 67,6 67,6 @@ int task_run(struct task *task, struct context *ctx) {
			return -1;
		}

		job_notify(ctx->state, pid, stat);
		update_job(ctx->state, pid, stat);
	}
}