libposix: initial changes to POSIX_kill

This commit is contained in:
2017-05-24 00:40:28 +02:00
parent 3381f75d03
commit 68bc46fe85
5 changed files with 110 additions and 39 deletions

View File

@@ -22,7 +22,7 @@
extern int *__libposix_errors_codes; extern int *__libposix_errors_codes;
extern WaitList **__libposix_wait_list; extern WaitList **__libposix_wait_list;
extern Child **__libposix_child_list; extern ChildList **__libposix_child_list;
static int __initialized; static int __initialized;
static void static void
@@ -44,7 +44,7 @@ libposix_init(int argc, char *argv[], PosixInit init)
extern int *__libposix_sigchld_target_pid; extern int *__libposix_sigchld_target_pid;
WaitList *wait_list; WaitList *wait_list;
Child *child_list; ChildList *child_list;
int status; int status;
int error_codes[ERRNO_LAST-ERRNO_FIRST]; int error_codes[ERRNO_LAST-ERRNO_FIRST];
unsigned char signals_to_code[256]; 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 */ /* initialize child_list; used when SIGCHLD is enabled */
child_list = nil; child_list = nil;
__libposix_wait_list = &child_list; __libposix_child_list = &child_list;
/* initialize signal handling */ /* initialize signal handling */
memset(signals_to_code, 0, sizeof(signals_to_code)); memset(signals_to_code, 0, sizeof(signals_to_code));

View File

@@ -23,11 +23,11 @@ struct WaitList
WaitList *next; WaitList *next;
}; };
typedef struct Child Child; typedef struct ChildList ChildList;
struct Child struct ChildList
{ {
int pid; int pid;
Child *next; ChildList *next;
}; };
extern void __libposix_files_check_conf(void); 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 void __libposix_setup_new_process(void);
extern int __libposix_note_to_signal(char *note);

View File

@@ -23,7 +23,7 @@
extern char **environ; extern char **environ;
WaitList **__libposix_wait_list; WaitList **__libposix_wait_list;
Child **__libposix_child_list; ChildList **__libposix_child_list;
static PosixExitStatusTranslator __libposix_exit_status_translator; static PosixExitStatusTranslator __libposix_exit_status_translator;
static int __libposix_wnohang; static int __libposix_wnohang;
@@ -34,7 +34,6 @@ static int
fork_without_sigchld(int *errnop) fork_without_sigchld(int *errnop)
{ {
int pid = fork(); int pid = fork();
if(pid == 0) if(pid == 0)
__libposix_setup_new_process(); __libposix_setup_new_process();
return pid; return pid;
@@ -42,14 +41,6 @@ fork_without_sigchld(int *errnop)
int (*__libposix_fork)(int *errnop) = fork_without_sigchld; 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 void
__libposix_free_wait_list(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 void
POSIX_exit(int code) POSIX_exit(int code)
{ {

View File

@@ -24,7 +24,7 @@
/* rendezvous points */ /* rendezvous points */
extern unsigned char *__signals_to_code_map; extern unsigned char *__signals_to_code_map;
extern unsigned char *__code_to_signal_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 */ /* pointer to the pid to forward notes to */
int *__libposix_sigchld_target_pid; int *__libposix_sigchld_target_pid;
@@ -44,8 +44,24 @@ release_inherited_resources(void)
static void static void
forwarding_note_handler(void *ureg, char *note) forwarding_note_handler(void *ureg, char *note)
{ {
postnote(PNPROC, *__libposix_sigchld_target_pid, note); int sig;
noted(NCONT); 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 static void
@@ -93,6 +109,7 @@ fork_with_sigchld(int *errnop)
int p2c; int p2c;
long c2p = -1, child = -1; long c2p = -1, child = -1;
char proxy_name[256]; char proxy_name[256];
ChildList *c;
/* Father here: /* Father here:
* - create P2C * - create P2C
@@ -173,9 +190,11 @@ fork_with_sigchld(int *errnop)
break; break;
} }
/* TODO: register p2c among known children so that kill can /* no need to lock: the child list is private */
* handle them properly. c = malloc(sizeof(ChildList));
*/ c->pid = p2c;
c->next = *__libposix_child_list;
*__libposix_child_list = c;
return p2c; return p2c;
} }

View File

@@ -69,7 +69,7 @@
* Calling libposix_emulate_SIGCHLD() during libposix initialization * Calling libposix_emulate_SIGCHLD() during libposix initialization
* will enable this machinery for the whole life of the process. * 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 * Each fork() will spawn two additional processes that are designed
* to proxy signals between the parent and the desired child: * to proxy signals between the parent and the desired child:
@@ -162,7 +162,7 @@ terminated_by_signal(int sig)
} }
int int
send_control_msg(int pid, char *msg) __libposix_send_control_msg(int pid, char *msg)
{ {
int fd, n; int fd, n;
char buf[256]; char buf[256];
@@ -187,14 +187,13 @@ ErrorBeforeOpen:
return 0; return 0;
} }
/* Executes a PosixSignalDisposition for pid. /* Executes a PosixSignalDisposition.
*
* MUST be called by POSIX_kill for unblockable signals.
*/ */
static int static int
execute_disposition(int sig, PosixSignalDisposition action, int pid) execute_disposition(int sig, PosixSignalDisposition action)
{ {
switch(action){ switch(action){
case ResumeTheProcess: // the sender resumed us already
case SignalHandled: case SignalHandled:
return 1; return 1;
case TerminateTheProcess: case TerminateTheProcess:
@@ -202,17 +201,46 @@ execute_disposition(int sig, PosixSignalDisposition action, int pid)
terminated_by_signal(sig); terminated_by_signal(sig);
break; break;
case StopTheProcess: case StopTheProcess:
if(pid < 0) return __libposix_send_control_msg(getpid(), "stop");
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 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 static int
send_signal(int *errnop, int pid, int signal) send_signal(int *errnop, int pid, int signal)
{ {
@@ -324,21 +352,21 @@ POSIX_kill(int *errnop, int pid, int sig)
switch(signal){ switch(signal){
case PosixSIGKILL: case PosixSIGKILL:
if(pid > 0) if(pid > 0)
if(!send_control_msg(pid, "kill")){ if(!__libposix_send_control_msg(pid, "kill")){
*errnop = __libposix_get_errno(PosixEPERM); *errnop = __libposix_get_errno(PosixEPERM);
return -1; return -1;
} }
break; break;
case PosixSIGSTOP: case PosixSIGSTOP:
if(pid > 0) if(pid > 0)
if(!send_control_msg(pid, "stop")){ if(!__libposix_send_control_msg(pid, "stop")){
*errnop = __libposix_get_errno(PosixEPERM); *errnop = __libposix_get_errno(PosixEPERM);
return -1; return -1;
} }
break; break;
case PosixSIGCONT: case PosixSIGCONT:
if(pid > 0) if(pid > 0)
if(!send_control_msg(pid, "start")){ if(!__libposix_send_control_msg(pid, "start")){
*errnop = __libposix_get_errno(PosixEPERM); *errnop = __libposix_get_errno(PosixEPERM);
return -1; return -1;
} }
@@ -356,6 +384,11 @@ translate_jehanne_note(char *note)
return 0; return 0;
} }
int
__libposix_note_to_signal(char *note)
{
return atoi(note+__POSIX_SIGNAL_PREFIX_LEN);
}
int int
__libposix_note_handler(void *ureg, char *note) __libposix_note_handler(void *ureg, char *note)
@@ -364,7 +397,7 @@ __libposix_note_handler(void *ureg, char *note)
PosixSignalDisposition action; PosixSignalDisposition action;
if(strncmp(note, __POSIX_SIGNAL_PREFIX, __POSIX_SIGNAL_PREFIX_LEN) != 0) if(strncmp(note, __POSIX_SIGNAL_PREFIX, __POSIX_SIGNAL_PREFIX_LEN) != 0)
return translate_jehanne_note(note); // TODO: should we translate common notes? 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) if(sig < __min_known_sig || sig > __max_known_sig)
sysfatal("libposix: '%s' does not carry a signal", note); sysfatal("libposix: '%s' does not carry a signal", note);
*__handling_external_signal = 1; *__handling_external_signal = 1;