Print this page
OS-4470 lxbrand unblocking signals in new threads must be atomic
*** 89,100 ****
int c_sig; /* signal to send on thread exit */
void *c_stk; /* %esp of new thread */
void *c_ptidp;
struct lx_desc *c_ldtinfo; /* thread-specific segment */
void *c_ctidp;
! ucontext_t c_uc; /* original register state */
! sigset_t c_sigmask; /* signal mask */
lx_affmask_t c_affmask; /* CPU affinity mask */
volatile int *c_clone_res; /* pid/error returned to cloner */
int c_ptrace_event; /* ptrace(2) event for child stop */
void *c_ntv_stk; /* native stack for this thread */
size_t c_ntv_stk_sz; /* native stack size */
--- 89,99 ----
int c_sig; /* signal to send on thread exit */
void *c_stk; /* %esp of new thread */
void *c_ptidp;
struct lx_desc *c_ldtinfo; /* thread-specific segment */
void *c_ctidp;
! ucontext_t c_uc; /* original register state/sigmask */
lx_affmask_t c_affmask; /* CPU affinity mask */
volatile int *c_clone_res; /* pid/error returned to cloner */
int c_ptrace_event; /* ptrace(2) event for child stop */
void *c_ntv_stk; /* native stack for this thread */
size_t c_ntv_stk_sz; /* native stack size */
*** 237,264 ****
* thread-specific data structure with the stack list so that it may be
* freed at thread exit or fork(2).
*/
lx_install_stack(cs->c_ntv_stk, cs->c_ntv_stk_sz, lxtsd);
- if (sigprocmask(SIG_SETMASK, &cs->c_sigmask, NULL) < 0) {
- *(cs->c_clone_res) = -errno;
-
- lx_err_fatal("Unable to release held signals for child "
- "thread: %s", strerror(errno));
- }
-
/*
* Let the parent know that the clone has (effectively) been
* completed.
*/
*(cs->c_clone_res) = rval;
/*
! * We want to load the general registers from this context, and
! * switch to the BRAND stack.
*/
! cs->c_uc.uc_flags = UC_CPU;
cs->c_uc.uc_brand_data[0] = (void *)LX_UC_STACK_BRAND;
/*
* New threads will not link into the existing context chain.
*/
--- 236,257 ----
* thread-specific data structure with the stack list so that it may be
* freed at thread exit or fork(2).
*/
lx_install_stack(cs->c_ntv_stk, cs->c_ntv_stk_sz, lxtsd);
/*
* Let the parent know that the clone has (effectively) been
* completed.
*/
*(cs->c_clone_res) = rval;
/*
! * We want to load the general registers from this context, restore the
! * original signal mask, and switch to the BRAND stack. The original
! * signal mask was saved to the context by lx_clone().
*/
! cs->c_uc.uc_flags = UC_CPU | UC_SIGMASK;
cs->c_uc.uc_brand_data[0] = (void *)LX_UC_STACK_BRAND;
/*
* New threads will not link into the existing context chain.
*/
*** 279,298 ****
* Fire the ptrace(2) event stop in the new thread:
*/
lx_ptrace_stop_if_option(cs->c_ptrace_event, B_TRUE, 0, &cs->c_uc);
/*
! * Jump to the Linux process. The system call must not return.
*/
! if (syscall(SYS_brand, B_JUMP_TO_LINUX, &cs->c_uc) == -1) {
! lx_err_fatal("B_JUMP_TO_LINUX failed: %s",
! strerror(errno));
! }
! abort();
!
! /*NOTREACHED*/
! return (NULL);
}
/*
* The way Linux handles stopping for FORK vs. CLONE does not map exactly to
* which syscall was used. Instead, it has to do with which signal is set in
--- 272,284 ----
* Fire the ptrace(2) event stop in the new thread:
*/
lx_ptrace_stop_if_option(cs->c_ptrace_event, B_TRUE, 0, &cs->c_uc);
/*
! * Jump to the Linux process. This call cannot return.
*/
! lx_jump_to_linux(&cs->c_uc);
}
/*
* The way Linux handles stopping for FORK vs. CLONE does not map exactly to
* which syscall was used. Instead, it has to do with which signal is set in
*** 664,686 ****
"thread: %s", strerror(errno));
}
clone_res = 0;
- (void) sigfillset(&sigmask);
-
/*
* Block all signals because the thread we create won't be able to
* properly handle them until it's fully set up.
*/
if (sigprocmask(SIG_BLOCK, &sigmask, &osigmask) < 0) {
lx_debug("lx_clone sigprocmask() failed: %s", strerror(errno));
free(cs->c_lx_tsd);
free(cs);
return (-errno);
}
! cs->c_sigmask = osigmask;
/*
* Allocate the native stack for this new thread now, so that we
* can return failure gracefully as ENOMEM.
*/
--- 650,671 ----
"thread: %s", strerror(errno));
}
clone_res = 0;
/*
* Block all signals because the thread we create won't be able to
* properly handle them until it's fully set up.
*/
+ (void) sigfillset(&sigmask);
if (sigprocmask(SIG_BLOCK, &sigmask, &osigmask) < 0) {
lx_debug("lx_clone sigprocmask() failed: %s", strerror(errno));
free(cs->c_lx_tsd);
free(cs);
return (-errno);
}
! cs->c_uc.uc_sigmask = osigmask;
/*
* Allocate the native stack for this new thread now, so that we
* can return failure gracefully as ENOMEM.
*/