diff -urp src.old/winsup/cygwin/fork.cc src/winsup/cygwin/fork.cc --- src.old/winsup/cygwin/fork.cc Wed Jun 19 02:17:03 2002 +++ src/winsup/cygwin/fork.cc Fri Aug 16 12:43:55 2002 @@ -311,8 +311,6 @@ fork_child (HANDLE& hParent, dll *&first if ((*t)->clear_on_fork ()) (*t)->set (); - user_data->threadinterface->fixup_after_fork (); - /* Initialize signal/process handling */ sigproc_init (); __pthread_atforkchild (); diff -urp src.old/winsup/cygwin/thread.cc src/winsup/cygwin/thread.cc --- src.old/winsup/cygwin/thread.cc Fri Aug 16 11:46:06 2002 +++ src/winsup/cygwin/thread.cc Fri Aug 16 12:49:42 2002 @@ -301,6 +301,7 @@ MTinterface::Init (int forked) if (forked) return; + keys = NULL; mutexs = NULL; conds = NULL; semaphores = NULL; @@ -316,10 +317,29 @@ MTinterface::Init (int forked) #endif } +void +MTinterface::fixup_before_fork (void) +{ + pthread_key *key = keys; + debug_printf ("keys is %x",keys); + while (key) + { + key->fixup_before_fork (); + key = key->next; + } +} + /* This function is called from a single threaded process */ void MTinterface::fixup_after_fork (void) { + pthread_key *key = keys; + debug_printf ("keys is %x",keys); + while (key) + { + key->fixup_after_fork (); + key = key->next; + } pthread_mutex *mutex = mutexs; debug_printf ("mutexs is %x",mutexs); while (mutex) @@ -974,6 +994,8 @@ pthread_key::pthread_key (void (*destruc MT_INTERFACE->destructors. Insert (new pthread_key_destructor (destructor, this)); } + /* threadsafe addition is easy */ + next = (pthread_key *) InterlockedExchangePointer (&MT_INTERFACE->keys, this); } pthread_key::~pthread_key () @@ -981,6 +1003,18 @@ pthread_key::~pthread_key () if (pthread_key_destructor *dest = MT_INTERFACE->destructors.Remove (this)) delete dest; TlsFree (dwTlsIndex); + + /* I'm not 100% sure the next bit is threadsafe. I think it is... */ + if (MT_INTERFACE->keys == this) + InterlockedExchangePointer (&MT_INTERFACE->keys, this->next); + else + { + pthread_key *tempkey = MT_INTERFACE->keys; + while (tempkey->next && tempkey->next != this) + tempkey = tempkey->next; + /* but there may be a race between the loop above and this statement */ + InterlockedExchangePointer (&tempkey->next, this->next); + } } int @@ -998,6 +1032,21 @@ pthread_key::get () return TlsGetValue (dwTlsIndex); } +void +pthread_key::fixup_before_fork () +{ + fork_buf = get (); +} + +void +pthread_key::fixup_after_fork () +{ + dwTlsIndex = TlsAlloc (); + if (dwTlsIndex == TLS_OUT_OF_INDEXES) + api_fatal ("pthread_key::fixup_after_fork () failed to reallocate Tls storage"); + set (fork_buf); +} + /*pshared mutexs: * REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the @@ -1382,6 +1431,8 @@ __pthread_cancel (pthread_t thread) void __pthread_atforkprepare (void) { + MT_INTERFACE->fixup_before_fork (); + callback *cb = MT_INTERFACE->pthread_prepare; while (cb) { @@ -1404,6 +1455,8 @@ __pthread_atforkparent (void) void __pthread_atforkchild (void) { + MT_INTERFACE->fixup_after_fork (); + callback *cb = MT_INTERFACE->pthread_child; while (cb) { diff -urp src.old/winsup/cygwin/thread.h src/winsup/cygwin/thread.h --- src.old/winsup/cygwin/thread.h Fri Aug 16 11:46:06 2002 +++ src/winsup/cygwin/thread.h Fri Aug 16 12:38:11 2002 @@ -178,9 +178,15 @@ class pthread_key:public verifyable_obje public: DWORD dwTlsIndex; + void *fork_buf; + class pthread_key *next; + int set (const void *); void *get (); + void fixup_before_fork (); + void fixup_after_fork (); + pthread_key (void (*)(void *)); ~pthread_key (); }; @@ -399,12 +405,14 @@ public: callback *pthread_child; callback *pthread_parent; - // list of mutex's. USE THREADSAFE INSERTS AND DELETES. + // lists of pthread objects. USE THREADSAFE INSERTS AND DELETES. + class pthread_key * keys; class pthread_mutex * mutexs; class pthread_cond * conds; class semaphore * semaphores; void Init (int); + void fixup_before_fork (void); void fixup_after_fork (void); MTinterface ():reent_index (0), indexallocated (0), threadcount (1)