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;
|
extern ChildList **__libposix_child_list;
|
||||||
static int __initialized;
|
static int __initialized;
|
||||||
|
|
||||||
|
int *__libposix_sigchld_target_pid;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
libposix_check_configuration(void)
|
libposix_check_configuration(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,3 +49,7 @@ extern void __libposix_free_wait_list(void);
|
||||||
extern void __libposix_setup_new_process(void);
|
extern void __libposix_setup_new_process(void);
|
||||||
|
|
||||||
extern int __libposix_note_to_signal(char *note);
|
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
|
void
|
||||||
__libposix_setup_new_process(void)
|
__libposix_setup_new_process(void)
|
||||||
{
|
{
|
||||||
|
@ -177,6 +210,7 @@ POSIX_wait(int *errnop, int *status)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pid = w->pid;
|
pid = w->pid;
|
||||||
|
__libposix_forget_child(pid);
|
||||||
if(w->msg[0] != 0){
|
if(w->msg[0] != 0){
|
||||||
s = strstr(w->msg, __POSIX_EXIT_PREFIX);
|
s = strstr(w->msg, __POSIX_EXIT_PREFIX);
|
||||||
if(s){
|
if(s){
|
||||||
|
@ -262,6 +296,7 @@ WaitAgain:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pid = w->pid;
|
pid = w->pid;
|
||||||
|
__libposix_forget_child(pid);
|
||||||
if(w->msg[0] != 0){
|
if(w->msg[0] != 0){
|
||||||
s = strstr(w->msg, __POSIX_EXIT_PREFIX);
|
s = strstr(w->msg, __POSIX_EXIT_PREFIX);
|
||||||
if(s){
|
if(s){
|
||||||
|
|
|
@ -27,7 +27,7 @@ extern unsigned char *__code_to_signal_map;
|
||||||
extern ChildList **__libposix_child_list;
|
extern ChildList **__libposix_child_list;
|
||||||
|
|
||||||
/* pointer to the pid to forward notes to */
|
/* 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 CHILD_READY(pid) ((long)rendezvous(&__signals_to_code_map, (void*)(~(pid))))
|
||||||
#define C2P_READY(pid) ((long)rendezvous(&__code_to_signal_map, (void*)(~(pid))))
|
#define C2P_READY(pid) ((long)rendezvous(&__code_to_signal_map, (void*)(~(pid))))
|
||||||
|
|
|
@ -143,7 +143,7 @@ typedef enum PosixSignalDisposition
|
||||||
} PosixSignalDisposition;
|
} PosixSignalDisposition;
|
||||||
|
|
||||||
static int
|
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.
|
// TODO: loop over writable note files and post note.
|
||||||
*errnop = __libposix_get_errno(PosixEPERM);
|
*errnop = __libposix_get_errno(PosixEPERM);
|
||||||
|
@ -206,81 +206,6 @@ execute_disposition(int sig, PosixSignalDisposition action)
|
||||||
return 0;
|
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
|
static PosixSignalDisposition
|
||||||
default_signal_disposition(int code)
|
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
|
int
|
||||||
POSIX_kill(int *errnop, int pid, int sig)
|
POSIX_kill(int *errnop, int pid, int sig)
|
||||||
{
|
{
|
||||||
PosixSignals signal;
|
PosixSignals signal;
|
||||||
PosixSignalDisposition action;
|
PosixSignalDisposition action;
|
||||||
|
PosixError perror;
|
||||||
|
|
||||||
signal = __code_to_signal_map[sig];
|
signal = __code_to_signal_map[sig];
|
||||||
if(signal == 0
|
if(signal == 0
|
||||||
&&(sig < __sigrtmin || sig > __sigrtmax))
|
&&(sig < __sigrtmin || sig > __sigrtmax))
|
||||||
sysfatal("libposix: undefined signal %d", sig);
|
sysfatal("libposix: undefined signal %d", sig);
|
||||||
if(pid == getpid()){
|
if(pid == getpid())
|
||||||
if(__libposix_signal_trampoline(sig))
|
perror = __libposix_receive_signal(sig);
|
||||||
action = SignalHandled;
|
else
|
||||||
else
|
perror = dispatch_signal(pid, sig);
|
||||||
action = default_signal_disposition(sig);
|
if(perror != 0){
|
||||||
if(!execute_disposition(sig, action, -1)){
|
*errnop = __libposix_get_errno(perror);
|
||||||
*errnop = __libposix_get_errno(PosixEPERM);
|
return -1;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in New Issue