diff --git a/sys/src/lib/posix/initlib.c b/sys/src/lib/posix/initlib.c index 164a56a..6347fe1 100644 --- a/sys/src/lib/posix/initlib.c +++ b/sys/src/lib/posix/initlib.c @@ -22,7 +22,7 @@ extern int *__libposix_errors_codes; extern WaitList **__libposix_wait_list; -extern Child **__libposix_child_list; +extern ChildList **__libposix_child_list; static int __initialized; static void @@ -44,7 +44,7 @@ libposix_init(int argc, char *argv[], PosixInit init) extern int *__libposix_sigchld_target_pid; WaitList *wait_list; - Child *child_list; + ChildList *child_list; int status; int error_codes[ERRNO_LAST-ERRNO_FIRST]; unsigned char signals_to_code[256]; @@ -64,7 +64,7 @@ libposix_init(int argc, char *argv[], PosixInit init) /* initialize child_list; used when SIGCHLD is enabled */ child_list = nil; - __libposix_wait_list = &child_list; + __libposix_child_list = &child_list; /* initialize signal handling */ memset(signals_to_code, 0, sizeof(signals_to_code)); diff --git a/sys/src/lib/posix/internal.h b/sys/src/lib/posix/internal.h index 7a1a546..5dc899c 100644 --- a/sys/src/lib/posix/internal.h +++ b/sys/src/lib/posix/internal.h @@ -23,11 +23,11 @@ struct WaitList WaitList *next; }; -typedef struct Child Child; -struct Child +typedef struct ChildList ChildList; +struct ChildList { int pid; - Child *next; + ChildList *next; }; extern void __libposix_files_check_conf(void); @@ -48,3 +48,4 @@ extern void __libposix_free_wait_list(void); extern void __libposix_setup_new_process(void); +extern int __libposix_note_to_signal(char *note); diff --git a/sys/src/lib/posix/processes.c b/sys/src/lib/posix/processes.c index 27d7082..cc4cd37 100644 --- a/sys/src/lib/posix/processes.c +++ b/sys/src/lib/posix/processes.c @@ -23,7 +23,7 @@ extern char **environ; WaitList **__libposix_wait_list; -Child **__libposix_child_list; +ChildList **__libposix_child_list; static PosixExitStatusTranslator __libposix_exit_status_translator; static int __libposix_wnohang; @@ -34,7 +34,6 @@ static int fork_without_sigchld(int *errnop) { int pid = fork(); - if(pid == 0) __libposix_setup_new_process(); return pid; @@ -42,14 +41,6 @@ fork_without_sigchld(int *errnop) int (*__libposix_fork)(int *errnop) = fork_without_sigchld; -void -__libposix_setup_new_process(void) -{ - /* reset wait list for the child */ - *__libposix_wait_list = nil; - *__libposix_child_list = nil; -} - void __libposix_free_wait_list(void) { @@ -69,6 +60,33 @@ __libposix_free_wait_list(void) } } +void +__libposix_free_child_list(void) +{ + ChildList *l, *c; + + /* free the wait list as the memory is shared */ + l = *__libposix_child_list; + if(l != nil){ + *__libposix_child_list = nil; + do + { + c = l; + l = c->next; + free(c); + } + while (l != nil); + } +} + +void +__libposix_setup_new_process(void) +{ + /* reset wait list for the child */ + __libposix_free_wait_list(); + __libposix_free_child_list(); +} + void POSIX_exit(int code) { diff --git a/sys/src/lib/posix/sigchlds.c b/sys/src/lib/posix/sigchlds.c index 0153f2d..ad24ff4 100644 --- a/sys/src/lib/posix/sigchlds.c +++ b/sys/src/lib/posix/sigchlds.c @@ -24,7 +24,7 @@ /* rendezvous points */ extern unsigned char *__signals_to_code_map; extern unsigned char *__code_to_signal_map; -extern Child **__libposix_child_list; +extern ChildList **__libposix_child_list; /* pointer to the pid to forward notes to */ int *__libposix_sigchld_target_pid; @@ -44,8 +44,24 @@ release_inherited_resources(void) static void forwarding_note_handler(void *ureg, char *note) { - postnote(PNPROC, *__libposix_sigchld_target_pid, note); - noted(NCONT); + int sig; + PosixSignals psig; + if(strncmp(note, __POSIX_SIGNAL_PREFIX, __POSIX_SIGNAL_PREFIX_LEN) == 0){ + sig = __libposix_note_to_signal(note); + if(sig < __min_known_sig || sig > __max_known_sig){ + /* Ignore unknown signals */ + noted(NCONT); + } + psig = __code_to_signal_map[sig]; + switch(psig){ + + } + postnote(PNPROC, *__libposix_sigchld_target_pid, note); + noted(NCONT); + } else { + /* what happened? */ + noted(NDFLT); + } } static void @@ -93,6 +109,7 @@ fork_with_sigchld(int *errnop) int p2c; long c2p = -1, child = -1; char proxy_name[256]; + ChildList *c; /* Father here: * - create P2C @@ -173,9 +190,11 @@ fork_with_sigchld(int *errnop) break; } - /* TODO: register p2c among known children so that kill can - * handle them properly. - */ + /* no need to lock: the child list is private */ + c = malloc(sizeof(ChildList)); + c->pid = p2c; + c->next = *__libposix_child_list; + *__libposix_child_list = c; return p2c; } diff --git a/sys/src/lib/posix/signals.c b/sys/src/lib/posix/signals.c index 66808fa..5df2528 100644 --- a/sys/src/lib/posix/signals.c +++ b/sys/src/lib/posix/signals.c @@ -69,7 +69,7 @@ * Calling libposix_emulate_SIGCHLD() during libposix initialization * will enable this machinery for the whole life of the process. * - * Such emulation change the way fork and kill works. + * Such emulation changes the way POSIX_fork and POSIX_kill works. * * Each fork() will spawn two additional processes that are designed * to proxy signals between the parent and the desired child: @@ -162,7 +162,7 @@ terminated_by_signal(int sig) } int -send_control_msg(int pid, char *msg) +__libposix_send_control_msg(int pid, char *msg) { int fd, n; char buf[256]; @@ -187,14 +187,13 @@ ErrorBeforeOpen: return 0; } -/* Executes a PosixSignalDisposition for pid. - * - * MUST be called by POSIX_kill for unblockable signals. +/* Executes a PosixSignalDisposition. */ static int -execute_disposition(int sig, PosixSignalDisposition action, int pid) +execute_disposition(int sig, PosixSignalDisposition action) { switch(action){ + case ResumeTheProcess: // the sender resumed us already case SignalHandled: return 1; case TerminateTheProcess: @@ -202,17 +201,46 @@ execute_disposition(int sig, PosixSignalDisposition action, int pid) terminated_by_signal(sig); break; case StopTheProcess: - if(pid < 0) - sysfatal("libposix: signal %d with stop disposition reached process %d", sig, pid); - return send_control_msg(pid, "stop"); - case ResumeTheProcess: - if(pid < 0) - sysfatal("libposix: signal %d with continue disposition reached process %d", sig, pid); - return send_control_msg(pid, "start"); + return __libposix_send_control_msg(getpid(), "stop"); } return 0; } +PosixError +__libposix_receive_signal(int sig) +{ + if(__libposix_signal_trampoline(sig)) + action = SignalHandled; + else + action = default_signal_disposition(sig); + if(!execute_disposition(sig, action)) + return PosixEPERM; + return 0; +} + +PosixError +__libposix_notify_signal_to_process(int pid, int signal) +{ + char buf[128]; + int fd, n; + + snprint(buf, sizeof(buf), "/proc/%d/note", pid); + if(access(file, AWRITE) != 0){ + if(access(file, AEXIST) == 0) + return PosixEPERM; + else + return PosixESRCH; + } + + fd = open(buf, OWRITE); + if(fd < 0) + return PosixEPERM; + n = snprint(buf, sizeof(buf), __POSIX_SIGNAL_PREFIX "%d", signal); + write(fd, buf, n); + close(fd); + return 0; +} + static int send_signal(int *errnop, int pid, int signal) { @@ -324,21 +352,21 @@ POSIX_kill(int *errnop, int pid, int sig) switch(signal){ case PosixSIGKILL: if(pid > 0) - if(!send_control_msg(pid, "kill")){ + if(!__libposix_send_control_msg(pid, "kill")){ *errnop = __libposix_get_errno(PosixEPERM); return -1; } break; case PosixSIGSTOP: if(pid > 0) - if(!send_control_msg(pid, "stop")){ + if(!__libposix_send_control_msg(pid, "stop")){ *errnop = __libposix_get_errno(PosixEPERM); return -1; } break; case PosixSIGCONT: if(pid > 0) - if(!send_control_msg(pid, "start")){ + if(!__libposix_send_control_msg(pid, "start")){ *errnop = __libposix_get_errno(PosixEPERM); return -1; } @@ -356,6 +384,11 @@ translate_jehanne_note(char *note) return 0; } +int +__libposix_note_to_signal(char *note) +{ + return atoi(note+__POSIX_SIGNAL_PREFIX_LEN); +} int __libposix_note_handler(void *ureg, char *note) @@ -364,7 +397,7 @@ __libposix_note_handler(void *ureg, char *note) 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); + sig = __libposix_note_to_signal(note); if(sig < __min_known_sig || sig > __max_known_sig) sysfatal("libposix: '%s' does not carry a signal", note); *__handling_external_signal = 1;