[BUG] THAPI deadlocks on two simultaneous calls from the same Process

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[BUG] THAPI deadlocks on two simultaneous calls from the same Process

Martin McClure
In order to get around some problems, we recently started using THAPI
(the DLLCC threaded API) in a limited way. Certain tests started
hanging. After some investigation, it appears that if a Smalltalk
Process makes two THAPI calls simultaneously, the Process will deadlock
itself.

Here's a simple example that shows this:

interruptedTest
        "Make one THAPI call, then, before that one returns, interrupt the
process with another."

        "LinuxInterface interruptedTest"

        | thread |
        thread := [self tSleep: 10] fork.
        (Delay forSeconds: 1) wait.
        thread interruptWith: [self tHelloWorld]


------------

In this test, #tSleep makes a THAPI call to usleep(), and #tHelloWorld
makes a THAPI call to printf(). The complete test class is attached to
this message. We saw the initial problem on Windows, but this test was
run on Linux x86, VW 7.4.1, OE 7.4d.

When run, it leaves a Process waiting on a Semaphore. This seems to be
an internal Semaphore used by the OE to implement THAPI. Other than
introspection on the Process, I don't know of any way to access this
Semaphore from Smalltalk.

The behavior I'd expect is either:

1) THAPI would notice that one thread was already in use by the Process
and allocate another thread for the second call, or

2) THAPI would make the second call wait until the first call returned,
then proceed.

At any rate, deadlocking seems like a bug, and it's going to be a pain
to work around.

Regards,

-Martin


<?xml version="1.0"?>

<st-source>
<time-stamp>From VisualWorks®, 7.4.1 of May 30, 2006 on November 22, 2006 at 11:30:29 am</time-stamp>


<class>
<name>LinuxInterface</name>
<environment>Smalltalk</environment>
<super>External.ExternalInterface</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports>
                        LinuxInterfaceDictionary.*
                        </imports>
<category>BOSS</category>
<attributes>
<includeFiles></includeFiles>
<includeDirectories></includeDirectories>
<libraryFiles><item>/lib/libc.so.6</item></libraryFiles>
<libraryDirectories></libraryDirectories>
<beVirtual type="eval">false</beVirtual>
<optimizationLevel type="sym">debug</optimizationLevel>
<package>(none)</package>
</attributes>
</class>

<!-- -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -   -->


<methods>
<class-id>LinuxInterface class</class-id> <category>tests</category>

<body package="(none)" selector="interruptedTest">interruptedTest
        "Make one THAPI call, then, before that one returns, interrupt the process with another."

        "LinuxInterface interruptedTest"

        | thread |
        thread := [self tSleep: 10] fork.
        (Delay forSeconds: 1) wait.
        thread interruptWith: [self tHelloWorld]</body>

<body package="(none)" selector="tHelloWorld">tHelloWorld
        "LinuxInterface tHelloWorld"

        (self new)
                tprintf: 'Hello, World   ';
                tfflush: 0</body>

<body package="(none)" selector="tSleep:">tSleep: seconds
        "LinuxInterface tSleep: 3"

        self new tusleep: seconds * 1000000</body>
</methods>

<!-- -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -   -->


<methods>
<class-id>LinuxInterface</class-id> <category>procedures</category>

<body package="(none)" selector="tfflush:">tfflush: fptr
        &lt;C: int _threaded fflush(unsigned long fptr)&gt;
        self error: 'failed'</body>

<body package="(none)" selector="tprintf:">tprintf: format
        &lt;C: int _threaded printf(const char *format)&gt;
        self error: 'failed'</body>

<body package="(none)" selector="tusleep:">tusleep: usec
        &lt;C: int _threaded usleep(unsigned long usec)&gt;
        self error: 'failed'</body>
</methods>

</st-source>