Could Emacs be rewritten in Python?

Robin Munn rmunn at pobox.com
Tue Apr 15 17:45:02 EDT 2003


Paul Foley <see at below.invalid> wrote:
> On Mon, 14 Apr 2003 16:50:40 GMT, Robin Munn wrote:
> 
>> What I really want to know is why you would consider sample #1 "broken
>> and fragile code". I can't think of any circumstances where sample #1
>> would fail to achieve its desired effect. Can you?
> 
> What if another thread (B) does the same thing, and changes sys.stdout
> while this thread (A) is still inside the "try" block?  And if thread
> A runs its "finally" clause and resets sys.stdout while thread B is
> still in its "try" block, they screw each other.

This is the classic problem that arises when two threads need to use any
shared resource, isn't it? I wasn't considering threads at all when I
wrote those two code samples, so of course I didn't use locks to ensure
good behavior.

Actually, now that I start thinking about it, any kind of
save-and-restore mechanism would start to get pretty hairy around
threads, wouldn't it? Let's look at a hypothetical "with" construct:

    with sys.stdout = cStringIO.StringIO():
        function_that_prints()
        parse_text_from(sys.stdout)

Let's assume we have two threads executing this code, and that the
"with" statement uses thread-local storage to save the original values.
If the "with" statement implements some kind of locking mechanism, this
is what you'll get:

----------------------------------------------------------------------
Thread A:                               Thread B:

(saves sys.stdout)
function_that_prints()
parse_text_from(sys.stdout)
(restores sys.stdout)
                                        (saves sys.stdout)
                                        function_that_prints()
                                        parse_text_from(sys.stdout)
                                        (restores sys.stdout)
----------------------------------------------------------------------

No problems here, of course. But what if this execution order happens?

----------------------------------------------------------------------
Thread A:                               Thread B:

(saves sys.stdout)
                                        (saves sys.stdout)
function_that_prints()
                                        function_that_prints()
parse_text_from(sys.stdout)
(restores sys.stdout)
                                        parse_text_from(sys.stdout)
                                        (restores sys.stdout)
----------------------------------------------------------------------

Thread B's parse_text_from() will be trying to read from thread A's
original sys.stdout, which will probably fail.

I don't really see any good solutions other than a lock around the whole
with: statement, which is something that would be easy to do in a try
... finally block. But maybe you can come up with something.

-- 
Robin Munn <rmunn at pobox.com>
http://www.rmunn.com/
PGP key ID: 0x6AFB6838    50FF 2478 CFFB 081A 8338  54F7 845D ACFD 6AFB 6838




More information about the Python-list mailing list