In a message dated 4/6/2001 12:04:09 AM Eastern Daylight Time, [EMAIL PROTECTED] writes: > > I believe, on my 4th attempt, I may have correctly implemented Zoran's > > patches to the 3.3.1 code to avoid the crash. > > <snip> > > Hopefully all is well now. This stuff has to work now - Tcl 7.6 has been > > ripped out of 4.0 altogether! > > Well, first tests are encouraging. Seems we have a proper behaviour > now. I'll make little more testing these days but the impression is that > all should be ok. I've tested the 3.3.2 (nsd_v3_r3_p0 tag) but assume > that 4.+ should be ok as well. > > Thanks for your time and effort, Jim ! Well, actually Zoran, we should all thank you for tracking down the problem! BTW: The thread-data block model of the Tcl C API is very different from the AOLserver and Pthread thread local storage C API's. I'd encourage anyone using thread local storage to stick to the pthread/aolserver model if possible. It was specifically designed, via the iterative nature of it's cleanup callbacks, to handle the case of interfaces accidently re-initializing other interfaces during cleanup. For example, consider two extension, the Foo and Bar API's, which both use thread local storage initialized at startup like this: Ns_TlsAlloc(&barTls, DeleteBar); Ns_TlsAlloc(&fooTls, DeleteFoo); One could call GetBar to get a private, per-thread Bar thing and GetFoo to get a private, per-thread Foo thing. Perhaps GetBar looks like this: void Bar * GetBar(void) { Bar *bPtr = Ns_TlsGet(&barTls); if (bPtr == NULL) { bPtr = NewBar(); Ns_TlsSet(&barTls, bPtr); } return bPtr; } Now, what if DeleteFoo looks like this: void DeleteFoo(void *arg) { Foo *fPtr = arg; Bar *bPtr = GetBar(); ... do something with bPtr ... FreeFoo(fPtr); } Note that DeleteFoo calls GetBar and you know that DeleteFoo will be called at thread exit time. How can you guarantee DeleteFoo will be called before DeleteBar, especially if you didn't write Bar, you're just using it. The answer is you can't which is why the pthread and aolserver model run across all the cleanup callbacks in order and then, if necessary, call them all again until everything is clear out. In otherwords, the order of cleanup could be: DeleteFoo DeleteBar or it could be: DeleteBar DeleteFoo (re-initializes Bar as a side effect) ... DeleteBar (a second time) By default the code will give up after a few trys in which case there's probably a memory leak or something happing. In practice this never happens. Note the model of Tcl is different, relying on the exit handlers which could call some other code which had already been destroyed. I find the pthread/aolserver model more useful and all the code in the aolserver core and the modules we write at AOL are designed around that behavior, i.e., each interface is safe to initialize/cleanup multiple times if necessary. Most pthread's books have a good explaination of this and you can find the code at work in thread/tls.c. Hope this clears up any confusion. -Jim