[ python-Bugs-1167930 ] threading.Thread.join() cannot be interrupted by a Ctrl-C

SourceForge.net noreply at sourceforge.net
Sat Jul 28 17:20:08 CEST 2007


Bugs item #1167930, was opened at 2005-03-21 17:19
Message generated for change (Comment added) made by gildea
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1167930&group_id=5470

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Threads
Group: Python 2.5
Status: Open
Resolution: None
Priority: 5
Private: No
Submitted By: Nicholas Veeser (nveeser)
Assigned to: Nobody/Anonymous (nobody)
Summary: threading.Thread.join() cannot be interrupted by a Ctrl-C

Initial Comment:
I write a python program that that starts several
threads and then waits on them all.  If I use join() to
wait on the threads, there is no way to Stop the
process with Ctrl-C.  

Threading.Thread.join() uses a lock
(thread.allocate_lock())  to put itself on the
"wait_queue".    It then calls thread.Lock.acquire(),
which blocks indefinitely.  Lock.acquire() (at least in
POSIX) seems to work in such a way as to ignore any
signals.  (both semaphore and condition variable type).
    

PyThread_acquire_lock() will not return until the lock
is acquired, even if a signal is sent.   Effectively,
Ctrl-C is "masked" until the lock is released, (the
joined thread is done), and the main thread comes back
to the interpreter and handles the signal, producing a
KeyboardInterrupt Exception.  But not before the lock
is released, which is once the thread is finished,
which is too late if you want to kill the main thread
and have it gracefully stop its child threads.

So the "main" thread has no way to call, join() and
still respond to Ctrl-C in some way.

One solution could be to change threading.Thread.join()
to use other methods of synchronization which respond
to Ctrl-C more effectively.

Another solution would be to have Lock.acquire() throw
a KeyboardInterruped exception like other system calls.
 This IHMO would make the python objects behave more
like Java, which requires catching the
InterruptedException, giving the developer more control
over how to handle this case.

----------------------------------------------------------------------

Comment By: Stephen Gildea (gildea)
Date: 2007-07-28 11:20

Message:
Logged In: YES 
user_id=414932
Originator: NO

The workaround of calling join() with a timeout has a drawback:
Python's threading wait routine polls 20 times a second when
given any timeout.  All this polling can mean lots of CPU
interrupts/wakeups on an otherwise idle laptop and drain the
battery faster.

----------------------------------------------------------------------

Comment By: Brett Cannon (bcannon)
Date: 2005-03-27 14:02

Message:
Logged In: YES 
user_id=357491

The other bug report phansen is talking about is bug #1171023 (http://
www.python.org/sf/1171023).  Closed as a duplicate but it can still be
used 
for file uploads by phansen.

Also worth reading for its explanation.

----------------------------------------------------------------------

Comment By: Peter Hansen (phansen)
Date: 2005-03-26 10:22

Message:
Logged In: YES 
user_id=567267

It appears only the original submitter (and admins?) can
attach files, so I've attached the example workaround in the
other bug report that I submitted.  It makes more sense in
that one anyway.

----------------------------------------------------------------------

Comment By: Peter Hansen (phansen)
Date: 2005-03-26 09:59

Message:
Logged In: YES 
user_id=567267

Coincidentally this issue came up in a thread in
comp.lang.python just now.  See tim one's reply at
http://groups.google.ca/groups?selm=mailman.884.1111815188.1799.python-list%40python.org
which indicates that "it's simply not possible for Ctrl+C to
interrupt a mutex acquire".

A workaround is to be sure to call join() with a timeout
value, inside a loop if you absolutely need an indefinite
timeout, but that won't necessarily work because of a
different problem which I just reported as bug 1171023. 
There's a workaround for that problem too though, provided
you can subclass threading.Thread: provide your own join()
which wraps the builtin one and which attempts to release
the lock safely.  I'll attach an example if I can figure out
how... there's no option to do so on this particular page in
Sourceforge. :-(

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1167930&group_id=5470


More information about the Python-bugs-list mailing list