diff --git a/sys/include/posix.h b/sys/include/posix.h index 0908b36..98e6e64 100644 --- a/sys/include/posix.h +++ b/sys/include/posix.h @@ -32,6 +32,7 @@ typedef unsigned long clock_t; #define __POSIX_EXIT_PREFIX "posix error " +#define __POSIX_EXIT_SIGNAL_PREFIX "terminated by posix signal " #define __POSIX_SIGNAL_PREFIX "posix: " extern void POSIX_exit(int code) __attribute__((noreturn)); @@ -63,6 +64,22 @@ extern void POSIX_free(void *ptr); extern unsigned int POSIX_sleep(unsigned int seconds); extern int POSIX_pipe(int *errnop, int fildes[2]); +typedef enum PosixSignalDisposition +{ + SignalHandled = 0, /* the application handled the signal */ + TerminateTheProcess, + TerminateTheProcessAndCoreDump, + StopTheProcess, + ResumeTheProcess +} PosixSignalDisposition; + +/* Executes a PosixSignalDisposition for pid. + * + * MUST be called instead of POSIX_kill for unblockable signals. + */ +extern int POSIX_signal_execute(int sig, PosixSignalDisposition action, int pid); + + /* Library initialization */ #define _ERRNO_H // skip the Posix part, we just need the enum @@ -164,7 +181,7 @@ extern int libposix_translate_exit_status(PosixExitStatusTranslator translator); /* Dispatch the signal to the registered handlers. */ -typedef int (*PosixSignalTrampoline)(int signal); +typedef PosixSignalDisposition (*PosixSignalTrampoline)(int signal); extern int libposix_set_signal_trampoline(PosixSignalTrampoline trampoline); diff --git a/sys/src/lib/posix/processes.c b/sys/src/lib/posix/processes.c index d4e1602..13f949d 100644 --- a/sys/src/lib/posix/processes.c +++ b/sys/src/lib/posix/processes.c @@ -29,10 +29,9 @@ static int __libposix_wnohang; #define __POSIX_SIGNAL_PREFIX_LEN (sizeof(__POSIX_SIGNAL_PREFIX)-1) -void -POSIX_exit(int code) +static void +free_wait_list(void) { - char buf[64], *s; WaitList *wl, *c; /* free the wait list as the memory is shared */ @@ -47,6 +46,14 @@ POSIX_exit(int code) } while (wl != nil); } +} + +void +POSIX_exit(int code) +{ + char buf[64], *s; + + free_wait_list(); if(__libposix_exit_status_translator != nil &&(s = __libposix_exit_status_translator(code)) != nil){ @@ -73,6 +80,8 @@ POSIX_execve(int *errnop, const char *name, char * const*argv, char * const*env) __libposix_setup_exec_environment(env); } + free_wait_list(); + ret = sys_exec(name, argv); switch(ret){ case 0: @@ -93,7 +102,7 @@ POSIX_wait(int *errnop, int *status) Waitmsg *w; WaitList *l; char *s; - int ret = 0, pid; + int ret = 0, sig = 0, pid; l = *__libposix_wait_list; if(l != nil){ @@ -117,12 +126,22 @@ POSIX_wait(int *errnop, int *status) s += (sizeof(__POSIX_EXIT_PREFIX)/sizeof(char) - 1); ret = atoi(s); } else { - /* TODO: setup configurable interpretations */ - ret = 127; + s = strstr(w->msg, __POSIX_EXIT_SIGNAL_PREFIX); + if(s){ + s += (sizeof(__POSIX_EXIT_SIGNAL_PREFIX)/sizeof(char) - 1); + sig = atoi(s); + } else { + /* TODO: setup configurable interpretations */ + ret = 127; + } } } - if(status != nil) - *status = ret << 8; + if(status != nil){ + if(sig == 0) + *status = ret << 8; + else + *status = sig; + } free(w); return pid; } @@ -133,7 +152,7 @@ POSIX_waitpid(int *errnop, int reqpid, int *status, int options) Waitmsg *w; WaitList *c, **nl; char *s; - int ret = 0, nohang = 0, pid; + int ret = 0, sig = 0, nohang = 0, pid; if(options & __libposix_wnohang){ @@ -168,13 +187,14 @@ POSIX_waitpid(int *errnop, int reqpid, int *status, int options) nl = __libposix_wait_list; c = *nl; while(c != nil){ - *nl = c->next; if(c->pid == reqpid){ if(status != nil) *status = c->status; + *nl = c->next; free(c); return reqpid; } + nl = &c->next; c = *nl; } @@ -191,19 +211,32 @@ WaitAgain: s += (sizeof(__POSIX_EXIT_PREFIX)/sizeof(char) - 1); ret = atoi(s); } else { - /* TODO: setup configurable interpretations */ - ret = 127; + s = strstr(w->msg, __POSIX_EXIT_SIGNAL_PREFIX); + if(s){ + s += (sizeof(__POSIX_EXIT_SIGNAL_PREFIX)/sizeof(char) - 1); + sig = atoi(s); + } else { + /* TODO: setup configurable interpretations */ + ret = 127; + } } } if(pid == reqpid){ - if(status != nil) - *status = ret << 8; + if(status != nil){ + if(sig == 0) + *status = ret << 8; + else + *status = sig; + } return reqpid; } c = malloc(sizeof(WaitList)); c->next = nil; c->pid = pid; - c->status = ret << 8; + if(sig == 0) + c->status= ret << 8; + else + c->status = sig; *nl = c; if(!nohang) goto WaitAgain; @@ -289,14 +322,51 @@ translate_jehanne_note(char *note) return 0; } +static void +terminated_by_signal(int sig) +{ + char buf[64]; + + free_wait_list(); + + snprint(buf, sizeof(buf), __POSIX_EXIT_SIGNAL_PREFIX "%d", sig); + exits(buf); +} + +int +POSIX_signal_execute(int sig, PosixSignalDisposition action, int pid) +{ + switch(action){ + case SignalHandled: + return 1; + case TerminateTheProcess: + case TerminateTheProcessAndCoreDump: + terminated_by_signal(sig); + break; + case StopTheProcess: + if(pid < 0) + sysfatal("libposix: stop signal reached the target process"); + // TODO: write stop to ctl file + return 1; + case ResumeTheProcess: + if(pid < 0) + sysfatal("libposix: continue signal reached the target process"); + // TODO: write start to ctl file + return 1; + } + return 0; +} + int __libposix_note_handler(void *ureg, char *note) { int sig; + PosixSignalDisposition action; if(strncmp(note, __POSIX_SIGNAL_PREFIX, __POSIX_SIGNAL_PREFIX_LEN) != 0) return translate_jehanne_note(note); // TODO: should we translate common notes? sig = atoi(note+__POSIX_SIGNAL_PREFIX_LEN); - return __libposix_signal_trampoline(sig); + action = __libposix_signal_trampoline(sig); + return POSIX_signal_execute(sig, action, -1); } int