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 <C: int _threaded fflush(unsigned long fptr)> self error: 'failed'</body> <body package="(none)" selector="tprintf:">tprintf: format <C: int _threaded printf(const char *format)> self error: 'failed'</body> <body package="(none)" selector="tusleep:">tusleep: usec <C: int _threaded usleep(unsigned long usec)> self error: 'failed'</body> </methods> </st-source> |
Free forum by Nabble | Edit this page |