~emersion/mrsh

986ec39affa94f3e8b8fd0a75a27cf16f1fad26d — Simon Ser 8 months ago a6311b0
Send SIGHUP on exit only if job control is enabled
5 files changed, 28 insertions(+), 20 deletions(-)

M include/shell/job.h
M include/shell/process.h
M shell/job.c
M shell/process.c
M shell/shell.c
M include/shell/job.h => include/shell/job.h +4 -0
@@ 95,5 95,9 @@ struct mrsh_job *job_by_id(struct mrsh_state *state,
 * Return a string describing the process' state. `r` is a random boolean.
 */
const char *job_state_str(struct mrsh_job *job, bool r);
/**
 * Send SIGHUP to all running jobs.
 */
void broadcast_sighup_to_jobs(struct mrsh_state *state);

#endif

M include/shell/process.h => include/shell/process.h +0 -4
@@ 38,9 38,5 @@ int process_poll(struct mrsh_process *process);
 * Update the shell's state with a child process status.
 */
void update_process(struct mrsh_state *state, pid_t pid, int stat);
/**
 * Send SIGHUP to all child processes.
 */
void broadcast_sighup(struct mrsh_state *state);

#endif

M shell/job.c => shell/job.c +21 -1
@@ 182,6 182,11 @@ bool job_set_foreground(struct mrsh_job *job, bool foreground, bool cont) {

	assert(job->pgid > 0);

	if (!priv->job_control) {
		fprintf(stderr, "job_set_foreground called with job control disabled\n");
		return false;
	}

	// Don't try to continue the job if it's not stopped
	if (job_poll(job) != TASK_STATUS_STOPPED) {
		cont = false;


@@ 273,7 278,7 @@ static bool _job_wait(struct mrsh_state *state, pid_t pid, int options) {
			if (errno == EINTR) {
				continue;
			}
			perror("waitpid");
			fprintf(stderr, "waitpid(%d): %s\n", pid, strerror(errno));
			return false;
		}
		assert(ret == pid);


@@ 506,3 511,18 @@ const char *job_state_str(struct mrsh_job *job, bool r) {
		return "Done";
	}
}

void broadcast_sighup_to_jobs(struct mrsh_state *state) {
	struct mrsh_state_priv *priv = state_get_priv(state);
	assert(priv->job_control);

	for (size_t i = 0; i < priv->jobs.len; ++i) {
		struct mrsh_job *job = priv->jobs.data[i];
		if (job_poll(job) >= 0) {
			continue;
		}
		if (kill(-job->pgid, SIGHUP) != 0) {
			perror("kill");
		}
	}
}

M shell/process.c => shell/process.c +0 -14
@@ 80,17 80,3 @@ void update_process(struct mrsh_state *state, pid_t pid, int stat) {
		assert(false);
	}
}

void broadcast_sighup(struct mrsh_state *state) {
	struct mrsh_state_priv *priv = state_get_priv(state);

	for (size_t i = 0; i < priv->processes.len; ++i) {
		struct mrsh_process *proc = priv->processes.data[i];
		if (process_poll(proc) >= 0) {
			continue;
		}
		if (kill(proc->pid, SIGHUP) != 0) {
			perror("kill");
		}
	}
}

M shell/shell.c => shell/shell.c +3 -1
@@ 85,7 85,9 @@ static void call_frame_destroy(struct mrsh_call_frame *frame) {

void mrsh_state_destroy(struct mrsh_state *state) {
	struct mrsh_state_priv *priv = state_get_priv(state);
	broadcast_sighup(state);
	if (priv->job_control) {
		broadcast_sighup_to_jobs(state);
	}
	mrsh_hashtable_for_each(&priv->variables, state_var_finish_iterator, NULL);
	mrsh_hashtable_finish(&priv->variables);
	mrsh_hashtable_for_each(&priv->functions, state_fn_finish_iterator, NULL);