libposix: more code for signals
This commit is contained in:
parent
68bc46fe85
commit
a59b992ed4
|
@ -25,6 +25,8 @@ extern WaitList **__libposix_wait_list;
|
|||
extern ChildList **__libposix_child_list;
|
||||
static int __initialized;
|
||||
|
||||
int *__libposix_sigchld_target_pid;
|
||||
|
||||
static void
|
||||
libposix_check_configuration(void)
|
||||
{
|
||||
|
|
|
@ -49,3 +49,7 @@ extern void __libposix_free_wait_list(void);
|
|||
extern void __libposix_setup_new_process(void);
|
||||
|
||||
extern int __libposix_note_to_signal(char *note);
|
||||
|
||||
extern int __libposix_is_child(int pid);
|
||||
|
||||
extern void __libposix_forget_child(int pid);
|
||||
|
|
|
@ -79,6 +79,39 @@ __libposix_free_child_list(void)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
__libposix_is_child(int pid)
|
||||
{
|
||||
ChildList *l;
|
||||
|
||||
/* free the wait list as the memory is shared */
|
||||
l = *__libposix_child_list;
|
||||
while(l != nil){
|
||||
if(l->pid == pid)
|
||||
return 1;
|
||||
l = l->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
__libposix_forget_child(int pid)
|
||||
{
|
||||
ChildList **l, *c;
|
||||
|
||||
/* free the wait list as the memory is shared */
|
||||
l = __libposix_child_list;
|
||||
while(*l != nil){
|
||||
c = *l
|
||||
if(c->pid == pid){
|
||||
*l = c->next;
|
||||
free(c);
|
||||
return;
|
||||
}
|
||||
l = &c->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__libposix_setup_new_process(void)
|
||||
{
|
||||
|
@ -177,6 +210,7 @@ POSIX_wait(int *errnop, int *status)
|
|||
return -1;
|
||||
}
|
||||
pid = w->pid;
|
||||
__libposix_forget_child(pid);
|
||||
if(w->msg[0] != 0){
|
||||
s = strstr(w->msg, __POSIX_EXIT_PREFIX);
|
||||
if(s){
|
||||
|
@ -262,6 +296,7 @@ WaitAgain:
|
|||
return -1;
|
||||
}
|
||||
pid = w->pid;
|
||||
__libposix_forget_child(pid);
|
||||
if(w->msg[0] != 0){
|
||||
s = strstr(w->msg, __POSIX_EXIT_PREFIX);
|
||||
if(s){
|
||||
|
|
|
@ -27,7 +27,7 @@ extern unsigned char *__code_to_signal_map;
|
|||
extern ChildList **__libposix_child_list;
|
||||
|
||||
/* pointer to the pid to forward notes to */
|
||||
int *__libposix_sigchld_target_pid;
|
||||
extern int *__libposix_sigchld_target_pid;
|
||||
|
||||
#define CHILD_READY(pid) ((long)rendezvous(&__signals_to_code_map, (void*)(~(pid))))
|
||||
#define C2P_READY(pid) ((long)rendezvous(&__code_to_signal_map, (void*)(~(pid))))
|
||||
|
|
|
@ -143,7 +143,7 @@ typedef enum PosixSignalDisposition
|
|||
} PosixSignalDisposition;
|
||||
|
||||
static int
|
||||
note_all_writable_processes(int *errnop, char *note)
|
||||
note_all_writable_processes(int *errnop, int sig)
|
||||
{
|
||||
// TODO: loop over writable note files and post note.
|
||||
*errnop = __libposix_get_errno(PosixEPERM);
|
||||
|
@ -206,81 +206,6 @@ execute_disposition(int sig, PosixSignalDisposition action)
|
|||
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)
|
||||
{
|
||||
char msg[64], file[128];
|
||||
int mode;
|
||||
int ret;
|
||||
|
||||
snprint(msg, sizeof(msg), __POSIX_SIGNAL_PREFIX "%d", signal);
|
||||
switch(pid){
|
||||
case 0:
|
||||
mode = PNGROUP;
|
||||
break;
|
||||
case -1:
|
||||
return note_all_writable_processes(errnop, msg);
|
||||
default:
|
||||
if(pid < 0){
|
||||
mode = PNGROUP;
|
||||
pid = -pid;
|
||||
} else {
|
||||
mode = PNPROC;
|
||||
}
|
||||
}
|
||||
|
||||
snprint(file, sizeof(file), "/proc/%d/note", pid);
|
||||
if(access(file, AWRITE) != 0){
|
||||
if(access(file, AEXIST) == 0)
|
||||
*errnop = __libposix_get_errno(PosixEPERM);
|
||||
else
|
||||
*errnop = __libposix_get_errno(PosixESRCH);
|
||||
return -1;
|
||||
}
|
||||
ret = postnote(mode, pid, msg);
|
||||
if(ret != 0){
|
||||
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_kill);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static PosixSignalDisposition
|
||||
default_signal_disposition(int code)
|
||||
{
|
||||
|
@ -328,53 +253,102 @@ default_signal_disposition(int code)
|
|||
}
|
||||
}
|
||||
|
||||
PosixError
|
||||
__libposix_receive_signal(int sig)
|
||||
{
|
||||
PosixSignalDisposition action;
|
||||
PosixSignals psig = __code_to_signal_map[sig];
|
||||
|
||||
if(psig != PosixSIGKILL && psig != PosixSIGSTOP
|
||||
&& __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((fd = open(buf, OWRITE)) < 0){
|
||||
if(access(buf, AEXIST) == 0)
|
||||
return PosixEPERM;
|
||||
else
|
||||
return PosixESRCH;
|
||||
}
|
||||
n = snprint(buf, sizeof(buf), __POSIX_SIGNAL_PREFIX "%d", signal);
|
||||
write(fd, buf, n);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PosixError
|
||||
__libposix_notify_signal_to_group(int pid, int signal)
|
||||
{
|
||||
char buf[128];
|
||||
int fd, n;
|
||||
|
||||
snprint(buf, sizeof(buf), "/proc/%d/notepg", pid);
|
||||
if((fd = open(buf, OWRITE)) < 0){
|
||||
if(access(buf, AEXIST) == 0)
|
||||
return PosixEPERM;
|
||||
else
|
||||
return PosixESRCH;
|
||||
}
|
||||
n = snprint(buf, sizeof(buf), __POSIX_SIGNAL_PREFIX "%d", signal);
|
||||
write(fd, buf, n);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PosixError
|
||||
dispatch_signal(int pid, int sig)
|
||||
{
|
||||
PosixSignals signal;
|
||||
PosixError error;
|
||||
switch(pid){
|
||||
case 0:
|
||||
return __libposix_notify_signal_to_group(getpid(), sig);
|
||||
case -1:
|
||||
return note_all_writable_processes(sig);
|
||||
default:
|
||||
if(pid < 0)
|
||||
return __libposix_notify_signal_to_group(-pid, sig);
|
||||
break;
|
||||
}
|
||||
signal = __code_to_signal_map[sig];
|
||||
error = __libposix_notify_signal_to_process(pid, sig);
|
||||
if(signal == PosixSIGCONT && !__libposix_is_child(pid))
|
||||
__libposix_send_control_msg(pid, "start");
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
POSIX_kill(int *errnop, int pid, int sig)
|
||||
{
|
||||
PosixSignals signal;
|
||||
PosixSignalDisposition action;
|
||||
PosixError perror;
|
||||
|
||||
signal = __code_to_signal_map[sig];
|
||||
if(signal == 0
|
||||
&&(sig < __sigrtmin || sig > __sigrtmax))
|
||||
sysfatal("libposix: undefined signal %d", sig);
|
||||
if(pid == getpid()){
|
||||
if(__libposix_signal_trampoline(sig))
|
||||
action = SignalHandled;
|
||||
else
|
||||
action = default_signal_disposition(sig);
|
||||
if(!execute_disposition(sig, action, -1)){
|
||||
*errnop = __libposix_get_errno(PosixEPERM);
|
||||
return -1;
|
||||
}
|
||||
if(pid == getpid())
|
||||
perror = __libposix_receive_signal(sig);
|
||||
else
|
||||
perror = dispatch_signal(pid, sig);
|
||||
if(perror != 0){
|
||||
*errnop = __libposix_get_errno(perror);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(signal){
|
||||
case PosixSIGKILL:
|
||||
if(pid > 0)
|
||||
if(!__libposix_send_control_msg(pid, "kill")){
|
||||
*errnop = __libposix_get_errno(PosixEPERM);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case PosixSIGSTOP:
|
||||
if(pid > 0)
|
||||
if(!__libposix_send_control_msg(pid, "stop")){
|
||||
*errnop = __libposix_get_errno(PosixEPERM);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case PosixSIGCONT:
|
||||
if(pid > 0)
|
||||
if(!__libposix_send_control_msg(pid, "start")){
|
||||
*errnop = __libposix_get_errno(PosixEPERM);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return send_signal(errnop, pid, sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
Loading…
Reference in New Issue