# \[Bug #2724\] fork from other than the main thread causes wrong pthread condition on NetBSD

**URL:** <https://www.ruby-forum.com/t/bug-2724-fork-from-other-than-the-main-thread-causes-wrong-pthread-condition-on-netbsd/183131>\
**Category:** Development\
**Created:** [February 8, 2010, 7:12pm UTC](https://www.ruby-forum.com/t/bug-2724-fork-from-other-than-the-main-thread-causes-wrong-pthread-condition-on-netbsd/183131 "2010-02-08T19:12:44Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Yui\_NARUSE](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/8edcca/32.png) [@Yui\_NARUSE](https://www.ruby-forum.com/u/Yui_NARUSE)\
**Post date:** [February 8, 2010, 7:12pm UTC](https://www.ruby-forum.com/t/bug-2724-fork-from-other-than-the-main-thread-causes-wrong-pthread-condition-on-netbsd/183131/1 "2010-02-08T19:12:44Z")

</div>

Bug #2724: fork from other than the main thread causes wrong pthread  
condition on NetBSD  
[http://redmine.ruby-lang.org/issues/show/2724](http://redmine.ruby-lang.org/issues/show/2724)

e$B5/I\<\<Te(B: Yui NARUSE  
e$B%9%F!\<%?%9e(B: Third Party’s Issue, e$BM%@hEYe(B: Normal  
e$B%+%F%4%je(B: core  
ruby -v: ruby 1.9.2dev (2010-02-07 trunk 26615) [i386-netbsdelf5.0.1]

NetBSD 5.0.[01] e$B$K$\*$$$F!"e(Bmain thread e$B0J30$Ne(B pthread  
e$B$+$ie(B fork e$B$9$k$H!“e(B  
pthread e$B$H%+!\<%M%k%9%l%C%Ie(B (lwp)  
e$B$H$N4XO”$,2u$l$k$H$$$&8=\>]$,3NG’$5$l$F$$$^$9!#e(B

e$B8e=R$N%Q%C%A$,$“$^$j$K%”%l$J$N$G$3$NLdBj$Oe(B Third Party’s Issue  
e$B$H$7!“e(B  
Ruby e$BB&$G$O=$@5$rF~$l$J$$;v$H$7$^$9$,!”\>pJs$N6&M-$H5-O?$N$?$a$Ke(B  
e$B$3$3$K%A%1%C%H$r@Z$C$F$\*$-$^$9!#e(B

e$B$J$\*!“$3$Ne(B workaround e$B$N:n@.$K$Oe(B  
@\_enamie$B$5$s$N=u$1$,$”$j$^$7$?!#e(B

# Index: thread\_pthread.c

— thread\_pthread.c (revision 26615)  
+++ thread\_pthread.c (working copy)  
@@ -17,6 +17,93 @@  
#include \<sys/resource.h\>  
#endif

+#if defined( **NetBSD\_Version** ) && **NetBSD\_Version** \>= 500000000  
+/\* Hack for NetBSD 5.0.x’s broken pthread-\>pt\_lid _/  
+/_ Copied from /src/lib/libpthread/pthread\_int.h _/  
+#define BROKEN\_PTHREAD\_T\_PT\_LID  
+#include \<lwp.h\>  
+#include \<pthread\_queue.h\>  
+#include \<sys/tree.h\>  
+  
+#define PTHREAD\_KEYS\_MAX 256  
+#define PTHREAD\_\_UNPARK\_MAX 32  
+  
+/_

- 
  - The size of this structure needs to be no larger than struct

- 
  - \_\_pthread\_cleanup\_store, defined in pthread.h.

- \*/  
+struct pt\_clean\_t {
- 

```
  PTQ_ENTRY(pt_clean_t) ptc_next;

```

- 

```
  void (*ptc_cleanup)(void *);

```

- 

```
  void *ptc_arg;

```

+};  
+  
+struct pthread\_lock\_ops {

- 

```
  void (*plo_init)(__cpu_simple_lock_t *);

```

- 

```
  int (*plo_try)(__cpu_simple_lock_t *);

```

- 

```
  void (*plo_unlock)(__cpu_simple_lock_t *);

```

- 

```
  void (*plo_lock)(__cpu_simple_lock_t *);

```

+};  
+  
+struct \_\_pthread\_st {

- 

```
  pthread_t pt_self; /* Must be first. */

```

- 

```
  unsigned int pt_magic; /* Magic number */

```

- 

```
  int pt_state; /* running, blocked, etc. */

```

- 

```
  pthread_mutex_t pt_lock; /* lock on state */

```

- 

```
  int pt_flags; /* see PT_FLAG_* below */

```

- 

```
  int pt_cancel; /* Deferred cancellation */

```

- 

```
  int pt_errno; /* Thread-specific errno. */

```

- 

```
  stack_t pt_stack; /* Our stack */

```

- 

```
  void *pt_exitval; /* Read by pthread_join() */

```

- 

```
  char *pt_name; /* Thread's name, set by the 

```

app. \*/

- 

```
  int pt_willpark; /* About to park */

```

- 

```
  lwpid_t pt_unpark; /* Unpark this when parking */

```

- 

```
  struct pthread_lock_ops pt_lockops;/* Cached to avoid PIC 

```

overhead \*/

- 

```
  pthread_mutex_t *pt_droplock; /* Drop this lock if cancelled 

```

\*/

- 

```
  pthread_cond_t pt_joiners; /* Threads waiting to join. */

```

- 
- 

```
  /* Threads to defer waking, usually until 

```

pthread\_mutex\_unlock(). \*/

- 

```
  lwpid_t pt_waiters[PTHREAD__UNPARK_MAX];

```

- 

```
  size_t pt_nwaiters;

```

- 
- 

```
  /* Stack of cancellation cleanup handlers and their arguments */

```

- 

```
  PTQ_HEAD(, pt_clean_t) pt_cleanup_stack;

```

- 
- 

```
  /* LWP ID and entry on the list of all threads. */

```

- 

```
  lwpid_t pt_lid;

```

- 

```
  RB_ENTRY(__pthread_st) pt_alltree;

```

- 

```
  PTQ_ENTRY(__pthread_st) pt_allq;

```

- 

```
  PTQ_ENTRY(__pthread_st) pt_deadq;

```

- 
- 

```
  /*

```

- 

```
   * General synchronization data. We try to align, as threads

```

- 

```
   * on other CPUs will access this data frequently.

```

- 

```
   */

```

- 

```
  int pt_dummy1 __aligned(128);

```

- 

```
  struct lwpctl *pt_lwpctl; /* Kernel/user comms area */

```

- 

```
  volatile int pt_blocking; /* Blocking in userspace */

```

- 

```
  volatile int pt_rwlocked; /* Handed rwlock successfully */

```

- 

```
  volatile int pt_signalled; /* Received 

```

pthread\_cond\_signal() \*/

- 

```
  volatile int pt_mutexwait; /* Waiting to acquire mutex */

```

- 

```
  void * volatile pt_mutexnext; /* Next thread in chain */

```

- 

```
  void * volatile pt_sleepobj; /* Object slept on */

```

- 

```
  PTQ_ENTRY(__pthread_st) pt_sleep;

```

- 

```
  void (*pt_early)(void *);

```

- 

```
  int pt_dummy2 __aligned(128);

```

- 
- 

```
  /* Thread-specific data. Large so it sits close to the end. */

```

- 

```
  int pt_havespecific;

```

- 

```
  void *pt_specific[PTHREAD_KEYS_MAX];

```

- 
- 

```
  /*

```

- 

```
   * Context for thread creation. At the end as it's cached

```

- 

```
   * and then only ever passed to _lwp_create().

```

- 

```
   */

```

- 

```
  ucontext_t pt_uc;

```

+};  
+#endif /\* **NetBSD** \*/  
+  
+  
static void native\_mutex\_lock(pthread\_mutex\_t \*lock);  
static void native\_mutex\_unlock(pthread\_mutex\_t \*lock);  
static int native\_mutex\_trylock(pthread\_mutex\_t \*lock);  
@@ -833,6 +920,9 @@  
native\_reset\_timer\_thread(void)  
{  
timer\_thread\_id = 0;  
+#ifdef BROKEN\_PTHREAD\_T\_PT\_LID

- ((struct \_\_pthread\_st \*)pthread\_self())-\>pt\_lid = \_lwp\_self();  
+#endif  
}

#ifdef HAVE\_SIGALTSTACK

---

<div class="post-metadata">

**Author:** ![Yui\_NARUSE](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/8edcca/32.png) [@Yui\_NARUSE](https://www.ruby-forum.com/u/Yui_NARUSE)\
**Post date:** [April 6, 2010, 12:20pm UTC](https://www.ruby-forum.com/t/bug-2724-fork-from-other-than-the-main-thread-causes-wrong-pthread-condition-on-netbsd/183131/2 "2010-04-06T12:20:27Z")

</div>

e$B%A%1%C%He(B #2724 e$B$,99?7$5$l$^$7$?!#e(B (by Michael G.)

I have made a patch (which was based upon this problem report) to  
NetBSD-current two weeks ago. I do not recommend this patch be  
accepted, but instead be marked as a “OS vendor problem” and fixed as  
such.

## I have requested a pull-up request to the NetBSD release engineers as well, for NetBSD 5.x, which should make it in the next NetBSD 5.x release on that path.

[http://redmine.ruby-lang.org/issues/show/2724](http://redmine.ruby-lang.org/issues/show/2724)

---

<div class="post-metadata">

**Author:** ![Yui\_NARUSE](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/8edcca/32.png) [@Yui\_NARUSE](https://www.ruby-forum.com/u/Yui_NARUSE)\
**Post date:** [April 6, 2010, 12:50pm UTC](https://www.ruby-forum.com/t/bug-2724-fork-from-other-than-the-main-thread-causes-wrong-pthread-condition-on-netbsd/183131/3 "2010-04-06T12:50:54Z")

</div>

e$B%A%1%C%He(B #2724 e$B$,99?7$5$l$^$7$?!#e(B (by Usaku NAKAMURA)

Original reporter Naruse says that  
“This is a problem of OS itself.  
Following patch is only a sample of the workaround.  
We shouldn’t apply this patch to ruby.  
I leave it only the record for the sharing of knowledge.”

So, this ticket has been already marked as “Third Party’s Issue”.

## BTW, it’s very good news that this problem is fixed at NetBSD side. Thank you for giving a useful information!

[http://redmine.ruby-lang.org/issues/show/2724](http://redmine.ruby-lang.org/issues/show/2724)
