ThreadWithException question

John Arbash Meinel john at arbash-meinel.com
Tue Aug 31 20:30:25 BST 2010


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hey Vincent-

I was looking over the code, and I saw something I thought was kind of
odd. Specifically this interaction:

class ThreadWithException
...
    def run(self):
        """Overrides Thread.run to capture any exception."""
        self.ready.clear()
        try:
            try:
                super(ThreadWithException, self).run()
            except:
                self.exception = sys.exc_info()
        finally:
            # Make sure the calling thread is released
            self.ready.set()

vs

class TestingTCPServerInAThread(...):
...
    def start_server(self):
        self.server = self.create_server()
        self._server_thread = ThreadWithException(
            event=self.server.started,
            target=self.run_server)
        self._server_thread.start()
        # Wait for the server thread to start (i.e release the lock)
        self.server.started.wait()


Now, for starters the term 'server' appears to mean 4-5 different
things, which gets a bit confusing.

However the key bit is to notice that 'start_server' is creating a
ThreadWithException, starting it, and then waiting on the event to be
set before continuing.

However, if I read that correctly, ThreadWithException doesn't set its
'ready' flag until the thread has *finished* its run() method (in other
words the extra thread is complete and is returning).

Now I see this following:

...
        # Get the real address, especially the port
        self.host, self.port = self.server.server_address
        self._server_thread.name = self.server.server_address
        if debug_threads():
            sys.stderr.write('Server thread %s started\n'
                             % (self._server_thread.name,))
        # If an exception occured during the server start, it will get
raised,
        # otherwise, the server is blocked on its accept() call.
        self._server_thread.pending_exception()
        # From now on, we'll use a different event to ensure the server
can set
        # its exception
        self._server_thread.set_ready_event(self.server.stopped)

^- It seems *very* strange to be setting the "I'm ready" event to "I'm
stopping".

In fact, I have the feeling that the code you really want is:

        self._server_thread = ThreadWithException(
            event=self.server.started,
            target=self.run_server)

to actually be:
        self._server_thread = ThreadWithException(
            event=self.server.stopped,
            target=self.run_server)

I suppose maybe the logic is:
  self.server should be setting the 'self.server.started' flag when it
  is ready to communicate. However, if it fails to actually startup
  properly, we don't want to be waiting forever. So have the Thread's
  "I'm exiting" statement set the Event.

If this is true, then I suggest we document it a bit better, and not
call it 'set_ready_event' since that is misleading. You had it by a
different name earlier, but I didn't actually understand what was going
on. It really isn't the "ready" event, but actually the
"thread_has_stopped" event. (As it is set when the thread is finishing
its 'run()' call.)

John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkx9WFEACgkQJdeBCYSNAAOI8QCgusEI257UnH6qNLZvvY4TI21d
0pIAnRn++pTM+Tm5t5a1wRMJb46tw87X
=XqqR
-----END PGP SIGNATURE-----



More information about the bazaar mailing list