This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Threading issue in cygwin python 2.5.1-2 ?


Jim Kleckner wrote:
Larry Hall (Cygwin) wrote:
Steve Holden wrote:
Igor Peshansky wrote:
On Wed, 5 Sep 2007, Steve Holden wrote:

Running the example on the above Python system I just see the command
prompt return with no program output whatsoever:


sholden@bigboy ~/Projects/Python
$ /usr/bin/python test03.py
So it fails, but doesn't bring up the exception dialog.
That's right: nothing at all. But note I compiled this particular version
myself, so I guess it's possible I didn't enable threads.

What's the exit code? The behavior sounds suspiciously like a missing DLL
case...

sholden@bigboy ~/Projects/Python $ /usr/bin/python test03.py

sholden@bigboy ~/Projects/Python
$ echo $?
0

So, what does this tell us?


Everything is just perfect! ;-)

The value would be non-zero if it couldn't find a needed DLL.



I also get 0 exit code even though there is a dialog box with the application error codes mentioned before.

[jim@kleckner2 ~]$ python aspn-threading-tkinter.py
[jim@kleckner2 ~]$ echo $?
0
[jim@kleckner2 ~]$

Ok, so I downloaded the python source and built a debug version
with:
export EXTRA_CFLAGS="-DPy_DEBUG -DPy_REF_DEBUG -DPy_TRACE_REFS -DPYMALLOC_DEBUG -DCOUNT_ALLOCS"
./configure --with-pydebug --prefix=$Prefix --mandir='${prefix}/share/man'


Now I run the example and similar to Steve it just exits with no dialog box.
With some extra print statements, it seems to disappear at the line:
        self.master.after(100, self.periodicCall)

Running this under gdb gives:

(gdb) run aspn-threading-tkinter.py
Starting program: /usr/bin/python.exe aspn-threading-tkinter.py
Loaded symbols for /cygdrive/c/WINDOWS/system32/ntdll.dll
Loaded symbols for /cygdrive/c/WINDOWS/system32/kernel32.dll
Loaded symbols for /usr/bin/cygwin1.dll
Loaded symbols for /cygdrive/c/WINDOWS/system32/advapi32.dll
Loaded symbols for /cygdrive/c/WINDOWS/system32/rpcrt4.dll
Loaded symbols for /usr/bin/libpython2.5.dll

Program exited with code 030000000005.
(gdb)

Running it with idle does give the exception dialog.

I can't seem to grab hold of anything to get a traceback.
Suggestions?
# From http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/82965
"""
This recipe describes how to handle asynchronous I/O in an environment where
you are running Tkinter as the graphical user interface. Tkinter is safe
to use as long as all the graphics commands are handled in a single thread.
Since it is more efficient to make I/O channels to block and wait for something
to happen rather than poll at regular intervals, we want I/O to be handled
in separate threads. These can communicate in a threasafe way with the main,
GUI-oriented process through one or several queues. In this solution the GUI
still has to make a poll at a reasonable interval, to check if there is
something in the queue that needs processing. Other solutions are possible,
but they add a lot of complexity to the application.

Created by Jacob Hall?n, AB Strakt, Sweden. 2001-10-17
"""
import Tkinter
import time
import threading
import random
import Queue

class GuiPart:
    def __init__(self, master, queue, endCommand):
        self.queue = queue
        # Set up the GUI
        console = Tkinter.Button(master, text='Done', command=endCommand)
        console.pack()
        # Add more GUI stuff here

    def processIncoming(self):
        """
        Handle all the messages currently in the queue (if any).
        """
        while self.queue.qsize():
            try:
                msg = self.queue.get(0)
                # Check contents of message and do what it says
                # As a test, we simply print it
                print msg
            except Queue.Empty:
                pass
        print "done processIncoming"

class ThreadedClient:
    """
    Launch the main part of the GUI and the worker thread. periodicCall and
    endApplication could reside in the GUI part, but putting them here
    means that you have all the thread controls in a single place.
    """
    def __init__(self, master):
        """
        Start the GUI and the asynchronous threads. We are in the main
        (original) thread of the application, which will later be used by
        the GUI. We spawn a new thread for the worker.
        """
        print "__init__"
        self.master = master

        # Create the queue
        print "Queue"
        self.queue = Queue.Queue()

        # Set up the GUI part
        print "GuiPart"
        self.gui = GuiPart(master, self.queue, self.endApplication)

        # Set up the thread to do asynchronous I/O
        # More can be made if necessary
        self.running = 1
        print "running"
    	self.thread1 = threading.Thread(target=self.workerThread1)
        self.thread1.start()

        # Start the periodic call in the GUI to check if the queue contains
        # anything
        print "peridicCall"
        self.periodicCall()

    def periodicCall(self):
        """
        Check every 100 ms if there is something new in the queue.
        """
        print "processIncoming"
        self.gui.processIncoming()
        if not self.running:
            # This is the brutal stop of the system. You may want to do
            # some cleanup before actually shutting it down.
            print "exiting"
            import sys
            sys.exit(1)
        print "self.master.after"
        self.master.after(100, self.periodicCall)
        print "done periodicCall"

    def workerThread1(self):
        """
        This is where we handle the asynchronous I/O. For example, it may be
        a 'select()'.
        One important thing to remember is that the thread has to yield
        control.
        """
        print "workerThread1"
        while self.running:
            # To simulate asynchronous I/O, we create a random number at
            # random intervals. Replace the following 2 lines with the real
            # thing.
            time.sleep(rand.random() * 0.3)
            msg = rand.random()
            self.queue.put(msg)

    def endApplication(self):
        print "endApplication"
        self.running = 0

rand = random.Random()
root = Tkinter.Tk()

client = ThreadedClient(root)
root.mainloop()
--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]