tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

_lwp_create change



Hello,

This issue came up recently with the go language signal tests failing.
The problem is that NetBSD copies the l_sigstk on lwp_creation and if
threads happen to get signals at the same time, then they share the
signal stack and they die (if sigaltstack is set). Go attempts to work
around this by blocking the signals (setting the signal mask on lwp
creation, and then calling sigaltstack() itself):


...
        var uc ucontextt
        getcontext(unsafe.Pointer(&uc))
                        
        uc.uc_flags = _UC_SIGMASK | _UC_CPU
        uc.uc_link = nil
        uc.uc_sigmask = sigset_all
                        
        lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, funcPC(netbsdMstart))

        ret := lwp_create(unsafe.Pointer(&uc), 0, unsafe.Pointer(&mp.procid))
...

Unfortunately this does not work (setting the mask this way) so we have
to explicitly do it using sigprocmask(); then later in netbsdMstart(), we
also have to set the stack with sigaltstack()? Wouldn't it nice if setting
_UC_SIGMASK set the signal mask and setting _UC_STACK set the signal stack
on lwp creation? Here's an untested diff:

There are a few questions?
- the current _lwp_makecontext code calls getcontext(), so it sets
  _UC_STACK and _UC_SIGMASK... We can ignore those settings if we
  want (although I believe these already contain the right values)
  for the existing _lwp_makecontext code by making LWP_UCONTEXT a
  user flag, so only new code passes it. This overloads the meaning
  of _UC_STACK on lwp creation to mean "set the signal stack".
- 32 bit processes need special treatment (to pass a regular ucontext_t
  not a ucontext32_t)

What do you think?

christos

Index: sys/lwp.h
===================================================================
RCS file: /cvsroot/src/sys/sys/lwp.h,v
retrieving revision 1.173
diff -u -u -r1.173 lwp.h
--- sys/lwp.h	8 Apr 2017 00:25:50 -0000	1.173
+++ sys/lwp.h	19 Apr 2017 21:49:23 -0000
@@ -551,6 +551,7 @@
 #define	LWP_SUSPENDED	0x00000080
 
 /* Kernel-internal flags for LWP creation. */
+#define LWP_UCONTEXT	0x20000000
 #define	LWP_PIDLID	0x40000000
 #define	LWP_VFORK	0x80000000
 
Index: kern/kern_lwp.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_lwp.c,v
retrieving revision 1.187
diff -u -u -r1.187 kern_lwp.c
--- kern/kern_lwp.c	14 Jan 2017 19:32:10 -0000	1.187
+++ kern/kern_lwp.c	19 Apr 2017 21:49:23 -0000
@@ -904,8 +904,12 @@
 	} else
 		l2->l_prflag = 0;
 
-	l2->l_sigstk = l1->l_sigstk;
-	l2->l_sigmask = l1->l_sigmask;
+	ucontext_t *uc = (flags & LWP_UCONTEXT) != 0 ? arg : NULL;
+
+	l2->l_sigstk = uc && (uc->uc_flags & _UC_STACK) ? uc->uc_stack :
+	    l1->l_sigstk;
+	l2->l_sigmask = uc && (uc->uc_flags & _UC_SIGMASK) ? uc->uc_sigmask :
+	    l1->l_sigmask;
 	TAILQ_INIT(&l2->l_sigpend.sp_info);
 	sigemptyset(&l2->l_sigpend.sp_set);
 
Index: kern/sys_lwp.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sys_lwp.c,v
retrieving revision 1.58
diff -u -u -r1.58 sys_lwp.c
--- kern/sys_lwp.c	15 Jan 2017 01:28:14 -0000	1.58
+++ kern/sys_lwp.c	19 Apr 2017 21:49:24 -0000
@@ -84,7 +84,11 @@
 	if (__predict_false(uaddr == 0))
 		return ENOMEM;
 
-	error = lwp_create(l, p, uaddr, flags & LWP_DETACHED,
+	flags &= LWP_DETACHED;
+	// XXX: notyet LWP_UCONTEXT is bad for netbsd32
+	flags |= (p->p_flags & PK_32) ? 0 : LWP_UCONTEXT;
+
+	error = lwp_create(l, p, uaddr, flags,
 	    NULL, 0, p->p_emul->e_startlwp, arg, &l2, l->l_class);
 	if (__predict_false(error)) {
 		uvm_uarea_free(uaddr);



Home | Main Index | Thread Index | Old Index