libposix: initial changes to POSIX_kill
This commit is contained in:
parent
3381f75d03
commit
68bc46fe85
@ -22,7 +22,7 @@
|
||||
|
||||
extern int *__libposix_errors_codes;
|
||||
extern WaitList **__libposix_wait_list;
|
||||
extern Child **__libposix_child_list;
|
||||
extern ChildList **__libposix_child_list;
|
||||
static int __initialized;
|
||||
|
||||
static void
|
||||
@ -44,7 +44,7 @@ libposix_init(int argc, char *argv[], PosixInit init)
|
||||
extern int *__libposix_sigchld_target_pid;
|
||||
|
||||
WaitList *wait_list;
|
||||
Child *child_list;
|
||||
ChildList *child_list;
|
||||
int status;
|
||||
int error_codes[ERRNO_LAST-ERRNO_FIRST];
|
||||
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 */
|
||||
child_list = nil;
|
||||
__libposix_wait_list = &child_list;
|
||||
__libposix_child_list = &child_list;
|
||||
|
||||
/* initialize signal handling */
|
||||
memset(signals_to_code, 0, sizeof(signals_to_code));
|
||||
|
@ -23,11 +23,11 @@ struct WaitList
|
||||
WaitList *next;
|
||||
};
|
||||
|
||||
typedef struct Child Child;
|
||||
struct Child
|
||||
typedef struct ChildList ChildList;
|
||||
struct ChildList
|
||||
{
|
||||
int pid;
|
||||
Child *next;
|
||||
ChildList *next;
|
||||
};
|
||||
|
||||
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 int __libposix_note_to_signal(char *note);
|
||||
|
@ -23,7 +23,7 @@
|
||||
extern char **environ;
|
||||
|
||||
WaitList **__libposix_wait_list;
|
||||
Child **__libposix_child_list;
|
||||
ChildList **__libposix_child_list;
|
||||
|
||||
static PosixExitStatusTranslator __libposix_exit_status_translator;
|
||||
static int __libposix_wnohang;
|
||||
@ -34,7 +34,6 @@ static int
|
||||
fork_without_sigchld(int *errnop)
|
||||
{
|
||||
int pid = fork();
|
||||
|
||||
if(pid == 0)
|
||||
__libposix_setup_new_process();
|
||||
return pid;
|
||||
@ -42,14 +41,6 @@ fork_without_sigchld(int *errnop)
|
||||
|
||||
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
|
||||
__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
|
||||
POSIX_exit(int code)
|
||||
{
|
||||
|
@ -24,7 +24,7 @@
|
||||
/* rendezvous points */
|
||||
extern unsigned char *__signals_to_code_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 */
|
||||
int *__libposix_sigchld_target_pid;
|
||||
@ -44,8 +44,24 @@ release_inherited_resources(void)
|
||||
static void
|
||||
forwarding_note_handler(void *ureg, char *note)
|
||||
{
|
||||
postnote(PNPROC, *__libposix_sigchld_target_pid, note);
|
||||
noted(NCONT);
|
||||
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);
|
||||
noted(NCONT);
|
||||
} else {
|
||||
/* what happened? */
|
||||
noted(NDFLT);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -93,6 +109,7 @@ fork_with_sigchld(int *errnop)
|
||||
int p2c;
|
||||
long c2p = -1, child = -1;
|
||||
char proxy_name[256];
|
||||
ChildList *c;
|
||||
|
||||
/* Father here:
|
||||
* - create P2C
|
||||
@ -173,9 +190,11 @@ fork_with_sigchld(int *errnop)
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: register p2c among known children so that kill can
|
||||
* handle them properly.
|
||||
*/
|
||||
/* no need to lock: the child list is private */
|
||||
c = malloc(sizeof(ChildList));
|
||||
c->pid = p2c;
|
||||
c->next = *__libposix_child_list;
|
||||
*__libposix_child_list = c;
|
||||
|
||||
return p2c;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@
|
||||
* Calling libposix_emulate_SIGCHLD() during libposix initialization
|
||||
* 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
|
||||
* to proxy signals between the parent and the desired child:
|
||||
@ -162,7 +162,7 @@ terminated_by_signal(int sig)
|
||||
}
|
||||
|
||||
int
|
||||
send_control_msg(int pid, char *msg)
|
||||
__libposix_send_control_msg(int pid, char *msg)
|
||||
{
|
||||
int fd, n;
|
||||
char buf[256];
|
||||
@ -187,14 +187,13 @@ ErrorBeforeOpen:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Executes a PosixSignalDisposition for pid.
|
||||
*
|
||||
* MUST be called by POSIX_kill for unblockable signals.
|
||||
/* Executes a PosixSignalDisposition.
|
||||
*/
|
||||
static int
|
||||
execute_disposition(int sig, PosixSignalDisposition action, int pid)
|
||||
execute_disposition(int sig, PosixSignalDisposition action)
|
||||
{
|
||||
switch(action){
|
||||
case ResumeTheProcess: // the sender resumed us already
|
||||
case SignalHandled:
|
||||
return 1;
|
||||
case TerminateTheProcess:
|
||||
@ -202,17 +201,46 @@ execute_disposition(int sig, PosixSignalDisposition action, int pid)
|
||||
terminated_by_signal(sig);
|
||||
break;
|
||||
case StopTheProcess:
|
||||
if(pid < 0)
|
||||
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 __libposix_send_control_msg(getpid(), "stop");
|
||||
}
|
||||
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)
|
||||
{
|
||||
@ -324,21 +352,21 @@ POSIX_kill(int *errnop, int pid, int sig)
|
||||
switch(signal){
|
||||
case PosixSIGKILL:
|
||||
if(pid > 0)
|
||||
if(!send_control_msg(pid, "kill")){
|
||||
if(!__libposix_send_control_msg(pid, "kill")){
|
||||
*errnop = __libposix_get_errno(PosixEPERM);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case PosixSIGSTOP:
|
||||
if(pid > 0)
|
||||
if(!send_control_msg(pid, "stop")){
|
||||
if(!__libposix_send_control_msg(pid, "stop")){
|
||||
*errnop = __libposix_get_errno(PosixEPERM);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case PosixSIGCONT:
|
||||
if(pid > 0)
|
||||
if(!send_control_msg(pid, "start")){
|
||||
if(!__libposix_send_control_msg(pid, "start")){
|
||||
*errnop = __libposix_get_errno(PosixEPERM);
|
||||
return -1;
|
||||
}
|
||||
@ -356,6 +384,11 @@ translate_jehanne_note(char *note)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__libposix_note_to_signal(char *note)
|
||||
{
|
||||
return atoi(note+__POSIX_SIGNAL_PREFIX_LEN);
|
||||
}
|
||||
|
||||
int
|
||||
__libposix_note_handler(void *ureg, char *note)
|
||||
@ -364,7 +397,7 @@ __libposix_note_handler(void *ureg, char *note)
|
||||
PosixSignalDisposition action;
|
||||
if(strncmp(note, __POSIX_SIGNAL_PREFIX, __POSIX_SIGNAL_PREFIX_LEN) != 0)
|
||||
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)
|
||||
sysfatal("libposix: '%s' does not carry a signal", note);
|
||||
*__handling_external_signal = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user