libposix: more code for signals

This commit is contained in:
Giacomo Tesio 2017-05-25 01:04:53 +02:00
parent 68bc46fe85
commit a59b992ed4
5 changed files with 128 additions and 113 deletions

View File

@ -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)
{

View File

@ -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);

View File

@ -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){

View File

@ -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))))

View File

@ -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