libposix: initial changes to POSIX_kill
This commit is contained in:
@@ -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));
|
||||||
|
@@ -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);
|
||||||
|
@@ -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)
|
||||||
{
|
{
|
||||||
|
@@ -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)
|
||||||
{
|
{
|
||||||
|
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);
|
postnote(PNPROC, *__libposix_sigchld_target_pid, note);
|
||||||
noted(NCONT);
|
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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user