Tcl8.1 threads blocking (Was: Re: Eggdev: Tcl8.1 threads fix patch)

Tothwolf tothwolf at concentric.net
Fri May 7 01:41:48 CST 1999


---------- Forwarded message ----------
Date: Fri, 7 May 1999 04:36:10 +0100
From: Jonathan Miles <jon at zetnet.net>
Reply-To: eggdev at eggheads.org
To: eggdev at eggheads.org
Subject: Re: Eggdev: Tcl8.1 threads fix patch

>Theres a call to Tcl_DoOneEvent() in the main() loop of eggdrop in
main.c.
>It's making a call to Tcl_WaitForEvent() which in turn is making a call
to
>Tcl_ConditionWait(), which is blocking...With its current flags a call to
>Tcl_DoOneEvent() isn't supposed to block...and dosen't, unless we are
>compiling Tcl8.1 with threads.
>
>I'm beginning to wonder if this is a bug in the design of Tcl8.1's
>threads...

Maybe... but this comment from tclUnixNotfy.c might explain a few
things...

    if (timePtr != NULL && timePtr->sec == 0 && timePtr->usec == 0) {
        /*
         * Cannot emulate a polling select with a polling condition
variable.
         * Instead, pretend to wait for files and tell the notifier
         * thread what we are doing.  The notifier thread makes sure
         * it goes through select with its select mask in the same state
         * as ours currently is.  We block until that happens.
         */

... it then goes and disables the TCL_DONT_WAIT flag by NULLifying timePtr
:/

        waitForFiles = 1;
        tsdPtr->pollState = POLL_WANT;
        timePtr = NULL;
    } else {

>From what I can see (I know abusolutely bugger all about tcl ;), there's
another thread that tcl spawns to notify us about events. To interact with
the other thread, it is using pthread_cond_wait. Would be much nicer if
the code could lock the mutex for the data/queue that the other 'notifier'
thread is going to check, and just check it itself. Obviously this
approach wouldnt work as well for a non-blocking call, but they could
certainly do this if timePtr->sec and timePtr->usec are 0. For anyone
that's interested, this is what's happening:

1.  We call Tcl_DoOneEvent(TCL_DONT_WAIT) which is supposed to be
non-blocking
2.    This then sets a timeout variable to 0 (bacause of DONT_WAIT) and
calls
    Tcl_WaitForEvent (Tcl_WaitForEvent (timePtr=0x0)). From the comments
in tclUnixNotfy.c:

 *      events on the message queue.  If the block time is 0, then
 *      Tcl_WaitForEvent just polls without blocking.

3. Tcl_WaitForEvent gets to the above pasted code and nullifies the
timePtr. Then it adds the current thread to a linked-list containing
threads waiting for (file) notification. After adding itself to the
linked-list, the code then calls Tcl_ConditionWait which presumably is
waiting for the 'notifier' thread to signal/awaken it. Wtf it cant do a
polling select if timePtr == {0,0} I dont know. The kernel should
serialise any select calls properly as it is, so it shouldnt matter if
another thread (ie the 'notifier' thread) is locked in a select call at
the same time.

Maybe someone could forward this message onto a person on the tcl
development team? I have no idea who that person would be, but they might
be able to help us :)) I'll patch tcl todo what I suggested in #3 above
and see if it causes any problems here.

PS. Sorry about the long e-mail ;)

-
Jonathan Miles <jon at zetnet.net>





More information about the Eggdev mailing list