The libpthread fork() wrapper makes two changes to the flags for the
process: it clears the 'detached' flag and sets the 'original' flag. I
now believe those are both wrong and should be left as they are from the
original process.
For the 'detached' flag, the POSIX spec does *not* mention the detached
state as changed by fork() and GNU libc doesn't change it across fork().
A ping to the austin-group mailing list appears to confirm this reading. I
apparently introduced this bug when I submitted the fork() wrapper before
I was a committer; about time I fixed it!
The 'original' flag just controls the result of the pthread_main_np()
function. The description of that function isn't 100% clear: "identifies
the main thread", ok, but where is "main thread" defined? We had
interpreted it as meaning "the first thread in *this* process", and so
would return 1 in the thread created by fork(). However it can also be
interpreted as "this thread's call history traces back to main()", which
is true of the child of fork() iff it was true in the parent, and is what
the THREAD_INITIAL_STACK flag already conveys. So I looked at the ports
tree and the only code that I can see using pthread_main_np() is
x11/gnustep/base where the latter semantic appears to be the desired
behavior. This diff thus eliminates the separate THREAD_ORIGINAL flag and
change pthread_main_np() to test THREAD_INITIAL_STACK.
So, any GNUstep users who can test this?
oks?
Philip Guenther
Index: rthread.c
===================================================================
RCS file: /data/src/openbsd/src/lib/librthread/rthread.c,v
retrieving revision 1.90
diff -u -p -r1.90 rthread.c
--- rthread.c 2 Apr 2016 19:56:53 -0000 1.90
+++ rthread.c 11 Apr 2016 04:37:28 -0000
@@ -193,7 +193,7 @@ _rthread_init(void)
thread->tid = getthrid();
thread->donesem.lock = _SPINLOCK_UNLOCKED_ASSIGN;
thread->flags |= THREAD_CANCEL_ENABLE | THREAD_CANCEL_DEFERRED |
- THREAD_ORIGINAL | THREAD_INITIAL_STACK;
+ THREAD_INITIAL_STACK;
thread->flags_lock = _SPINLOCK_UNLOCKED_ASSIGN;
strlcpy(thread->name, "Main process", sizeof(thread->name));
LIST_INSERT_HEAD(&_thread_list, thread, threads);
Index: rthread.h
===================================================================
RCS file: /data/src/openbsd/src/lib/librthread/rthread.h,v
retrieving revision 1.56
diff -u -p -r1.56 rthread.h
--- rthread.h 2 Apr 2016 19:00:51 -0000 1.56
+++ rthread.h 11 Apr 2016 04:37:39 -0000
@@ -189,7 +189,6 @@ struct pthread {
#define THREAD_CANCEL_DEFERRED 0x010
#define THREAD_CANCEL_DELAY 0x020
#define THREAD_DYING 0x040
-#define THREAD_ORIGINAL 0x080 /* original thread from fork */
#define THREAD_INITIAL_STACK 0x100 /* thread with stack from exec
*/
#define IS_CANCELED(thread) \
Index: rthread_fork.c
===================================================================
RCS file: /data/src/openbsd/src/lib/librthread/rthread_fork.c,v
retrieving revision 1.16
diff -u -p -r1.16 rthread_fork.c
--- rthread_fork.c 2 Apr 2016 19:00:51 -0000 1.16
+++ rthread_fork.c 11 Apr 2016 04:31:13 -0000
@@ -99,11 +99,7 @@ _dofork(int is_vfork)
/* update this thread's structure */
me->tid = getthrid();
me->donesem.lock = _SPINLOCK_UNLOCKED_ASSIGN;
- me->flags &= ~THREAD_DETACHED;
me->flags_lock = _SPINLOCK_UNLOCKED_ASSIGN;
-
- /* this thread is the initial thread for the new process */
- me->flags |= THREAD_ORIGINAL;
/* reinit the thread list */
LIST_INIT(&_thread_list);
Index: rthread_np.c
===================================================================
mRCS file: /data/src/openbsd/src/lib/librthread/rthread_np.c,v
retrieving revision 1.18
diff -u -p -r1.18 rthread_np.c
--- rthread_np.c 2 Apr 2016 19:00:51 -0000 1.18
+++ rthread_np.c 11 Apr 2016 04:38:09 -0000
@@ -47,8 +47,8 @@ pthread_set_name_np(pthread_t thread, co
int
pthread_main_np(void)
{
- return (!_threads_ready || (pthread_self()->flags & THREAD_ORIGINAL)
- ? 1 : 0);
+ return (!_threads_ready ||
+ (pthread_self()->flags & THREAD_INITIAL_STACK) ? 1 : 0);
}