[Python-Dev] Patch 595601

Tim Peters tim.one@comcast.net
Mon, 23 Jun 2003 21:06:29 -0400


[Greg Ewing]
> I don't think raising an exception is the right thing to do here. The
> closing thread hasn't really done anything wrong, it just happened to
> do the close at a moment that was inconvenient to another thread.

At the level of C streams, it's engaging in undefined behavior.  That's
always wrong, except when Python explicitly decides to provide semantics
beyond what C and POSIX specify.  As far as POSIX is concerned, what happens
when you close a stream while a read or write is in progress is undefined.

> I think the closing should simply be deferred until no operation on
> the file is in progress.

That's a possible semantic Python could layer on top of the platform
facilities, although it's not possible to do so in a bulletproof way (we
simply don't control C-level FILE* objects, and C code can screw us whatever
we try to do here; for example, it's flatly impossible for us to know
whether a file operation is in progress on a FILE* -- we can only add cruft
sufficient to tell whether the a file operation initiated by a Python file
object is in progress on its contained FILE*, and because the Python C API
has several functions that take (or return) FILE*s directly, that's not an
empty qualification).

> Another thing -- is this problem confined to just closing?

The specific segfault at issue is confined to closing, because that's the
only Python file-object operation that resets the Python file object's
stream to NULL.

> What if two threads perform some other operation on a file at the same
> time -- what stops them from interfering with each other?

It depends on the precise operations you have in mind.  If, for example,
you're talking about two threads reading at the same time, then the platform
stream library guarantees-- if it's threadsafe --that the reads will be
serialized.  OTOH, if you're talking about one thread reading and the other
writing, that's engaging in undefined behavior, and there's no predicting
the possible results.  For that matter, you don't need threads at all --
e.g., the effects of writing followed by reading on a single file by a
single thread, without an intervening flush or seek or reweind, are also
undefined.

> And whatever it is, why doesn't it stop closing from interfering with
> other operations?

Because Python resets a Python file object's stream to NULL when a Python
file object is closed, it guarantees a segfault in some cases where the
platform stream library may or may not have gone insane had the program been
mucking with streams directly.