Ctypes and C Infinite Callback Loops

Thomas Dimson tdimson at gmail.com
Tue Apr 8 19:49:27 EDT 2008


Hello,

I have quite a complex issue that is arising with regards to using
ctypes to hook into some legacy code. The legacy code is in infinite
loop - I can not touch this. It does some listening, and periodically
calls a specific callback function.

What I would like to be able to do is spawn a Python thread to handle
this infinite loop, and continue on my merry way. This works to an
extent, however if I try to raise the SystemExit exception (or any
other one) inside of this thread I get an error message of
"AssertionError: cannot join current thread".

I assume there is some issue with the global interpreter lock or that
you can't exit the infinite loop from above Python. Any suggestions on
how I can design this so the thread will be able to issue exits/raise
exceptions just like a regular thread? Is there a way of terminating
this thread from the python interpreter or ctypes.pythonapi?

I have also tried being sneaky by using a pthread in the C code, but I
had issues when I tried to create a new thread state using
ctypes.pythonapi (well, I had issues swapping it in when I get to the
callback). If this is the best solution, how do I create/swap in the
thread state from ctypes?

For some cooked up sample code that simulates this:

main.c (main.o -> main.so )
#include <stdio.h>
void loop( void (*callback)() )
{
    while( 1 )
    {
        callback();
        sleep(1);
    }
}

void testLoop( void (*callback)() )
{
    loop( callback );
}


************************************************
test.py:
import threading,ctypes,time,sys,os

soPath = os.path.join( "/home/tdimson/ctypes/main.so" )

class callLoop( threading.Thread ):
    def callback( self ):
        sys.exit()

    def run( self ):
        ctypes.cdll.LoadLibrary( soPath )
        mainLib = ctypes.CDLL( soPath )
        _callback =  ctypes.CFUNCTYPE( None )( self.callback )

        mainLib.testLoop( _callback )

loopThread = callLoop()
loopThread.start()

while 1:
    print "Not blocking"
    time.sleep(10)

********************************************

Then I execute: python test.py and get
Not blocking
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python2.4/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/usr/lib/python2.4/threading.py", line 634, in __exitfunc
    t.join()
  File "/usr/lib/python2.4/threading.py", line 532, in join
    assert self is not currentThread(), "cannot join current thread"
AssertionError: cannot join current thread
Error in sys.exitfunc:
Traceback (most recent call last):
  File "/usr/lib/python2.4/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/usr/lib/python2.4/threading.py", line 634, in __exitfunc
    t.join()
  File "/usr/lib/python2.4/threading.py", line 532, in join
    assert self is not currentThread(), "cannot join current thread"
AssertionError: cannot join current thread


Thanks for even reading this much :)

-Thomas Dimson



More information about the Python-list mailing list