[Python-ideas] Protecting finally clauses of interruptions

Yury Selivanov yselivanov.ml at gmail.com
Mon Apr 2 23:15:38 CEST 2012


On 2012-04-02, at 4:49 PM, Paul Colomiets wrote:
> It's complex, because if thread waits on a lock you can't determine if it's
> interrupted after lock or before. E.g. it's common to write:
> 
> l.lock()
> try:
>    ...
> finally:
>    l.unlock()
> 
> Which will break if you interrupted just after lock is acquired.

Yes, that's a good question.  However, I fail to see how just adding
'f_in_finally' solves the problem.

>> 3. Either add a special base exception, that can be thrown in a currently
>> executing frame to interrupt it, or add a special method to frame object
>> 'f_interrupt()'. Once a frame is attempted to be interrupted, it checks
>> its 'f_in_finally' counter.  If it is 0, then throw exception, if not -
>> wait till it sets back to 0 and throw exception immediately.
>> 
> 
> Not sure how it supposed to work. If it's coroutine it may yield
> while in finally, and you want it be interrupted only when it exits from
> finally.

And what's the problem with that?  It should be able to yield in its 
finally freely.

@coroutine
def read_data(connection):
  try:
    yield connection.recv()
  finally:
    yield connection.close()
  print('this shouldn't be printed if a timeout occurs')

yield read_data().with_timeout(0.1)

In the above example, if 'connection.recv()' takes longer than 0.1s to 
execute, the scheduler (trampoline) should interrupt the coroutine, 
'connection.abort()' line will be executed, and once connection is
aborted, it should stop the coroutine immediately.

As of now, if you throw an exception while generator is in its 'try'
block, everything will work as I explained.  The interpreter will
execute the 'finally' block, and propagate the exception at the end
of it.

However, if you throw an exception while generator in its 'finally'
block (!), then your coroutine will be aborted too early.  With your 
'f_in_finally' flag, scheduler simply won't try to interrupt the
coroutine, but, then the 'print(...)' line will be executed (!!) 
(and  it shouldn't really).  So, we need to shift the control of when
a frame is best to be interrupted to the interpreter, not the user 
code.

-
Yury



More information about the Python-ideas mailing list