Embedded Threading Question

hg hansgeunsmeyer at earthlink.net
Sun Dec 8 13:22:00 EST 2002


tpdietz at hotmail.com (Tim Dietz) wrote in message news:<32355ee1.0212061546.49a44902 at posting.google.com>...
> hansgeunsmeyer at earthlink.net (hg) wrote in message news:<95959723.0212041851.494f3479 at posting.google.com>...
> > tpdietz at hotmail.com (Tim Dietz) wrote in message news:<32355ee1.0212040738.3e7360ea at posting.google.com>...
> > 
> > > > How are you calling these C functions? Do the C functions call back into Python
> > > > (or do they have access to variables in your embedded Python app)?
> > > 
> > > Using SWIG, we create a Python module and a C++ wrapper class.  The Python
> > > module then has a class Foo, which we use to call methods that interface
> > > into the C++ Foo class.  So, in Python, I call Foo.SetValue(val) and the
> > > SetValue() method of the C++ Foo class is called.
> > > 
> > > Does that help to explain things better?
> > 
> > A little bit, it's still rather mysterious to me :) If the
> > non-threaded version works fine, and the threaded version doesn't, and
> > if the SetValue call really is the culprit, then it may be that you
> > have to protect the access to that value you are setting (I suppose
> > it's a class member, or else some global variable). I don't think SWIG
> > does this automatically.  So, in this case, you need to modify the
> > SWIG generated code, by using a lock around the access of the
> > variable.
> > 
> > 
> > Hans
> 
> OK, I'm getting closer.  I've trimmed down my Python code so that it
> has a thread to monitor the socket (ReadThread) as well as the main
> thread.
> 
> So, to simplify, there is a function (called SendMsg) that sends text
> to a TCP/IP server using socket.send().  The server sends a response
> back to the client.  The response is picked up in ReadThread and
> processed from there.  However, my problem occurs whether or not I
> process the data read from the socket, so I've eliminated that code. 
> In addition, the server can send asynchronous updates to this client,
> which are also processed in the ReadThread.
> 
> So, below is the streamlined version of my Python module (client.py):
> 
> def SendMsg(outmsg):
>    mysock.send(outmsg)
> 
> def ReadThread():
>    done = 0
>    buf = ''
>    while not done:
>       rcv,wr,err = select.select([mysock],[],[],0.1)
>       if mysock in rcv:
>          buf += rcv[0].recv(1000)

I've experimented a bit with a similar function:

done = 0
queue = Queue.Queue()
def ReadThread(mysock):
    global queue, done
    while 1:
            rcv,wr,err = select.select([mysock],[], [])
            if mysock in rcv:
                data = mysock.recv(1024)
                print 'Receiving: ', data 
                queue.put('ReadThread: ' + data)                
                if data.endswith('QUIT'):
                    done = 1
                    return

def UseReadThread1():
    global done
    done = 0
    mysock = socket(AF_INET, SOCK_STREAM)      
    mysock.connect((serverHost, serverPort))   
    thread.start_new(ReadThread, (mysock,))
    print "Sending ASYNCH"
    mysock.send("ASYNCH")
    time.sleep(2)        
    while not done:
        time.sleep(1)
    mysock.close()        

As server I used a simple echo-server.

Function ReadThread ran fine, also when running in a separate thread.
It also ran fine when I kept the socket open and let the server send
aynchronous updates back to the client. ("ASYNCH" would cause it to do
that; at some random moment it would echo back "QUIT" and close the
connection.)
When run in a GUI like IDLE, UseReadThread would generally cause
problems, even when run in a separate thread. (For instance, first run
would be ok, second one would hang IDLE).  But this was caused by the
two print statements (in ReadThread and in UseReadThread); commenting
them out, made it work fine in IDLE as well.

I don't quite understand why you'd want to separate sending and
receiving, and why you use a function like ReadThread at all. It seems
more natural (and less error-prone) to me to spawn a separate thread
for each client request, create a client socket inside that thread,
and there wait for the server to respond.

Hans



More information about the Python-list mailing list