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 WEXITED 0x00000004
|
||||||
#define WCONTINUED 0x00000008
|
#define WCONTINUED 0x00000008
|
||||||
#define WNOWAIT 0x01000000 /* Don't reap, just poll status. */
|
#define WNOWAIT 0x01000000 /* Don't reap, just poll status. */
|
||||||
|
#define __WCLONE 0x80000000
|
||||||
|
|
||||||
/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */
|
/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */
|
||||||
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
|
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
|
||||||
@@ -224,6 +225,9 @@ struct fork_tree_node {
|
|||||||
/* Store event related to signal. For example,
|
/* Store event related to signal. For example,
|
||||||
it represents that the proceess has been resumed by SIGCONT. */
|
it represents that the proceess has been resumed by SIGCONT. */
|
||||||
int signal_flags;
|
int signal_flags;
|
||||||
|
|
||||||
|
/* Store signal sent to parent when the process terminates. */
|
||||||
|
int termsig;
|
||||||
};
|
};
|
||||||
|
|
||||||
void hold_fork_tree_node(struct fork_tree_node *ftn);
|
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)
|
unsigned long sp, int clone_flags)
|
||||||
{
|
{
|
||||||
struct process *proc;
|
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,
|
if ((proc = ihk_mc_alloc_pages(KERNEL_STACK_NR_PAGES,
|
||||||
IHK_MC_AP_NOWAIT)) == NULL) {
|
IHK_MC_AP_NOWAIT)) == NULL) {
|
||||||
@@ -228,6 +233,8 @@ struct process *clone_process(struct process *org, unsigned long pc,
|
|||||||
goto err_free_sigshared;
|
goto err_free_sigshared;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc->ftn->termsig = termsig;
|
||||||
|
|
||||||
init_fork_tree_node(proc->ftn, (clone_flags & CLONE_VM) ? NULL : org->ftn,
|
init_fork_tree_node(proc->ftn, (clone_flags & CLONE_VM) ? NULL : org->ftn,
|
||||||
proc);
|
proc);
|
||||||
|
|
||||||
|
|||||||
@@ -389,7 +389,8 @@ SYSCALL_DECLARE(wait4)
|
|||||||
int empty = 1;
|
int empty = 1;
|
||||||
|
|
||||||
dkprintf("wait4,proc->pid=%d,pid=%d\n", proc->pid, pid);
|
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;
|
ret = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -399,6 +400,10 @@ SYSCALL_DECLARE(wait4)
|
|||||||
ihk_mc_spinlock_lock_noirq(&proc->ftn->lock);
|
ihk_mc_spinlock_lock_noirq(&proc->ftn->lock);
|
||||||
list_for_each_entry_safe(child_iter, next, &proc->ftn->children, siblings_list) {
|
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);
|
ihk_mc_spinlock_lock_noirq(&child_iter->lock);
|
||||||
|
|
||||||
if ((pid < 0 && -pid == child_iter->pgid) ||
|
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) {
|
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);
|
ihk_mc_spinlock_lock_noirq(&child_iter->lock);
|
||||||
|
|
||||||
if ((pid < 0 && -pid == child_iter->pgid) ||
|
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;
|
ftn->owner = NULL;
|
||||||
ihk_mc_spinlock_unlock_noirq(&ftn->lock);
|
ihk_mc_spinlock_unlock_noirq(&ftn->lock);
|
||||||
|
|
||||||
/* Send SIGCHLD to parent */
|
/* Send signal to parent */
|
||||||
if (ftn->parent) {
|
if (ftn->parent) {
|
||||||
int parent_owner_pid;
|
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 = ftn->parent->owner;
|
||||||
parent_owner_pid = parent_owner ? ftn->parent->owner->pid : 0;
|
parent_owner_pid = parent_owner ? ftn->parent->owner->pid : 0;
|
||||||
ihk_mc_spinlock_unlock_noirq(&ftn->parent->lock);
|
ihk_mc_spinlock_unlock_noirq(&ftn->parent->lock);
|
||||||
if (parent_owner) {
|
if (parent_owner && (ftn->termsig != 0)) {
|
||||||
struct siginfo info;
|
struct siginfo info;
|
||||||
|
|
||||||
memset(&info, '\0', sizeof info);
|
memset(&info, '\0', sizeof info);
|
||||||
info.si_signo = SIGCHLD;
|
info.si_signo = SIGCHLD;
|
||||||
info.si_code = sig? ((sig & 0x80)? CLD_DUMPED: CLD_KILLED): CLD_EXITED;
|
info.si_code = sig? ((sig & 0x80)? CLD_DUMPED: CLD_KILLED): CLD_EXITED;
|
||||||
info._sifields._sigchld.si_pid = proc->pid;
|
info._sifields._sigchld.si_pid = proc->pid;
|
||||||
info._sifields._sigchld.si_status = ((rc & 0x00ff) << 8) | (sig & 0xff);
|
info._sifields._sigchld.si_status = ((rc & 0x00ff) << 8) | (sig & 0xff);
|
||||||
dkprintf("terminate,kill SIGCHLD,target pid=%d\n",
|
dkprintf("terminate,kill %d,target pid=%d\n",
|
||||||
parent_owner_pid);
|
ftn->termsig, parent_owner_pid);
|
||||||
error = do_kill(ftn->parent->owner->pid, -1, SIGCHLD, &info);
|
error = do_kill(ftn->parent->owner->pid, -1, SIGCHLD, &info);
|
||||||
/*
|
/*
|
||||||
sigchld_parent(ftn->parent->owner, 0);
|
sigchld_parent(ftn->parent->owner, 0);
|
||||||
*/
|
*/
|
||||||
dkprintf("terminate,klll SIGCHLD,error=%d\n",
|
dkprintf("terminate,klll %d,error=%d\n",
|
||||||
error);
|
ftn->termsig, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
release_fork_tree_node(ftn->parent);
|
release_fork_tree_node(ftn->parent);
|
||||||
@@ -2363,13 +2373,16 @@ SYSCALL_DECLARE(ptrace)
|
|||||||
|
|
||||||
switch(request) {
|
switch(request) {
|
||||||
case PTRACE_TRACEME:
|
case PTRACE_TRACEME:
|
||||||
|
dkprintf("ptrace: PTRACE_TRACEME\n");
|
||||||
error = ptrace_traceme();
|
error = ptrace_traceme();
|
||||||
break;
|
break;
|
||||||
case PTRACE_KILL:
|
case PTRACE_KILL:
|
||||||
case PTRACE_CONT:
|
case PTRACE_CONT:
|
||||||
|
dkprintf("ptrace: PTRACE_KILL/CONT\n");
|
||||||
error = ptrace_wakeup_sig(pid, request, data);
|
error = ptrace_wakeup_sig(pid, request, data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
dkprintf("ptrace: unimplemented ptrace called.\n");
|
||||||
error = 0;
|
error = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user