diff options
Diffstat (limited to 'sys/compat/linux/linux_emul.c')
-rw-r--r-- | sys/compat/linux/linux_emul.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/sys/compat/linux/linux_emul.c b/sys/compat/linux/linux_emul.c index dc81553..eb10ca6 100644 --- a/sys/compat/linux/linux_emul.c +++ b/sys/compat/linux/linux_emul.c @@ -155,7 +155,7 @@ void linux_proc_exit(void *arg __unused, struct proc *p) { struct linux_emuldata *em; - int error; + int error, shared_flags, shared_xstat; struct thread *td = FIRST_THREAD_IN_PROC(p); int *child_clear_tid; struct proc *q, *nq; @@ -187,6 +187,8 @@ linux_proc_exit(void *arg __unused, struct proc *p) } EMUL_SHARED_WLOCK(&emul_shared_lock); + shared_flags = em->shared->flags; + shared_xstat = em->shared->xstat; LIST_REMOVE(em, threads); em->shared->refs--; @@ -196,6 +198,12 @@ linux_proc_exit(void *arg __unused, struct proc *p) } else EMUL_SHARED_WUNLOCK(&emul_shared_lock); + if ((shared_flags & EMUL_SHARED_HASXSTAT) != 0) { + PROC_LOCK(p); + p->p_xstat = shared_xstat; + PROC_UNLOCK(p); + } + if (child_clear_tid != NULL) { struct linux_sys_futex_args cup; int null = 0; @@ -257,6 +265,9 @@ linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp) if (__predict_false(imgp->sysent == &elf_linux_sysvec && p->p_sysent != &elf_linux_sysvec)) linux_proc_init(FIRST_THREAD_IN_PROC(p), p->p_pid, 0); + if (__predict_false(p->p_sysent == &elf_linux_sysvec)) + /* Kill threads regardless of imgp->sysent value */ + linux_kill_threads(FIRST_THREAD_IN_PROC(p), SIGKILL); if (__predict_false(imgp->sysent != &elf_linux_sysvec && p->p_sysent == &elf_linux_sysvec)) { struct linux_emuldata *em; @@ -334,3 +345,29 @@ linux_set_tid_address(struct thread *td, struct linux_set_tid_address_args *args EMUL_UNLOCK(&emul_lock); return 0; } + +void +linux_kill_threads(struct thread *td, int sig) +{ + struct linux_emuldata *em, *td_em, *tmp_em; + struct proc *sp; + + td_em = em_find(td->td_proc, EMUL_DONTLOCK); + + KASSERT(td_em != NULL, ("linux_kill_threads: emuldata not found.\n")); + + EMUL_SHARED_RLOCK(&emul_shared_lock); + LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) { + if (em->pid == td_em->pid) + continue; + + sp = pfind(em->pid); + if ((sp->p_flag & P_WEXIT) == 0) + psignal(sp, sig); + PROC_UNLOCK(sp); +#ifdef DEBUG + printf(LMSG("linux_kill_threads: kill PID %d\n"), em->pid); +#endif + } + EMUL_SHARED_RUNLOCK(&emul_shared_lock); +} |