Make __WCLONE option for wait4(2) and flags for clone(2) work properly.
This commit is contained in:
committed by
Tomoki Shirasawa
parent
66db108dd3
commit
2997274470
@@ -112,6 +112,7 @@
|
||||
#define WEXITED 0x00000004
|
||||
#define WCONTINUED 0x00000008
|
||||
#define WNOWAIT 0x01000000 /* Don't reap, just poll status. */
|
||||
#define __WCLONE 0x80000000
|
||||
|
||||
/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */
|
||||
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
|
||||
@@ -224,6 +225,9 @@ struct fork_tree_node {
|
||||
/* Store event related to signal. For example,
|
||||
it represents that the proceess has been resumed by SIGCONT. */
|
||||
int signal_flags;
|
||||
|
||||
/* Store signal sent to parent when the process terminates. */
|
||||
int termsig;
|
||||
};
|
||||
|
||||
void hold_fork_tree_node(struct fork_tree_node *ftn);
|
||||
|
||||
@@ -202,6 +202,11 @@ struct process *clone_process(struct process *org, unsigned long pc,
|
||||
unsigned long sp, int clone_flags)
|
||||
{
|
||||
struct process *proc;
|
||||
int termsig = clone_flags & 0xff;
|
||||
|
||||
if (termsig < 0 || _NSIG < termsig) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((proc = ihk_mc_alloc_pages(KERNEL_STACK_NR_PAGES,
|
||||
IHK_MC_AP_NOWAIT)) == NULL) {
|
||||
@@ -228,6 +233,8 @@ struct process *clone_process(struct process *org, unsigned long pc,
|
||||
goto err_free_sigshared;
|
||||
}
|
||||
|
||||
proc->ftn->termsig = termsig;
|
||||
|
||||
init_fork_tree_node(proc->ftn, (clone_flags & CLONE_VM) ? NULL : org->ftn,
|
||||
proc);
|
||||
|
||||
|
||||
@@ -389,7 +389,8 @@ SYSCALL_DECLARE(wait4)
|
||||
int empty = 1;
|
||||
|
||||
dkprintf("wait4,proc->pid=%d,pid=%d\n", proc->pid, pid);
|
||||
if (options & ~(WNOHANG | WUNTRACED | WCONTINUED)) {
|
||||
if (options & ~(WNOHANG | WUNTRACED | WCONTINUED | __WCLONE)) {
|
||||
dkprintf("wait4: unexpected options(%x).\n", options);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
@@ -399,6 +400,10 @@ SYSCALL_DECLARE(wait4)
|
||||
ihk_mc_spinlock_lock_noirq(&proc->ftn->lock);
|
||||
list_for_each_entry_safe(child_iter, next, &proc->ftn->children, siblings_list) {
|
||||
|
||||
if (!(!!(options & __WCLONE) ^ (child_iter->termsig == SIGCHLD))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(&child_iter->lock);
|
||||
|
||||
if ((pid < 0 && -pid == child_iter->pgid) ||
|
||||
@@ -439,6 +444,10 @@ SYSCALL_DECLARE(wait4)
|
||||
}
|
||||
list_for_each_entry_safe(child_iter, next, &proc->ftn->ptrace_children, ptrace_siblings_list) {
|
||||
|
||||
if (!(!!(options & __WCLONE) ^ (child_iter->termsig == SIGCHLD))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ihk_mc_spinlock_lock_noirq(&child_iter->lock);
|
||||
|
||||
if ((pid < 0 && -pid == child_iter->pgid) ||
|
||||
@@ -554,7 +563,7 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
|
||||
ftn->owner = NULL;
|
||||
ihk_mc_spinlock_unlock_noirq(&ftn->lock);
|
||||
|
||||
/* Send SIGCHLD to parent */
|
||||
/* Send signal to parent */
|
||||
if (ftn->parent) {
|
||||
int parent_owner_pid;
|
||||
|
||||
@@ -576,21 +585,22 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
|
||||
parent_owner = ftn->parent->owner;
|
||||
parent_owner_pid = parent_owner ? ftn->parent->owner->pid : 0;
|
||||
ihk_mc_spinlock_unlock_noirq(&ftn->parent->lock);
|
||||
if (parent_owner) {
|
||||
if (parent_owner && (ftn->termsig != 0)) {
|
||||
struct siginfo info;
|
||||
|
||||
memset(&info, '\0', sizeof info);
|
||||
info.si_signo = SIGCHLD;
|
||||
info.si_code = sig? ((sig & 0x80)? CLD_DUMPED: CLD_KILLED): CLD_EXITED;
|
||||
info._sifields._sigchld.si_pid = proc->pid;
|
||||
info._sifields._sigchld.si_status = ((rc & 0x00ff) << 8) | (sig & 0xff);
|
||||
dkprintf("terminate,kill SIGCHLD,target pid=%d\n",
|
||||
parent_owner_pid);
|
||||
dkprintf("terminate,kill %d,target pid=%d\n",
|
||||
ftn->termsig, parent_owner_pid);
|
||||
error = do_kill(ftn->parent->owner->pid, -1, SIGCHLD, &info);
|
||||
/*
|
||||
sigchld_parent(ftn->parent->owner, 0);
|
||||
*/
|
||||
dkprintf("terminate,klll SIGCHLD,error=%d\n",
|
||||
error);
|
||||
dkprintf("terminate,klll %d,error=%d\n",
|
||||
ftn->termsig, error);
|
||||
}
|
||||
|
||||
release_fork_tree_node(ftn->parent);
|
||||
@@ -2363,13 +2373,16 @@ SYSCALL_DECLARE(ptrace)
|
||||
|
||||
switch(request) {
|
||||
case PTRACE_TRACEME:
|
||||
dkprintf("ptrace: PTRACE_TRACEME\n");
|
||||
error = ptrace_traceme();
|
||||
break;
|
||||
case PTRACE_KILL:
|
||||
case PTRACE_CONT:
|
||||
dkprintf("ptrace: PTRACE_KILL/CONT\n");
|
||||
error = ptrace_wakeup_sig(pid, request, data);
|
||||
break;
|
||||
default:
|
||||
dkprintf("ptrace: unimplemented ptrace called.\n");
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user