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