[issue13812] multiprocessing package doesn't flush stderr on child exception

2012-01-17 Thread Jon Brandvein

New submission from Jon Brandvein :

When a child process exits due to an exception, a traceback is written, but 
stderr is not flushed. Thus I see a header like "Process 1:\n", but no 
traceback.

I don't have a development environment or any experience with Mecurial, so I'm 
afraid there's no patch, but it's a one-liner.

In   /Lib/multiprocess/process.py :: Process._bootstrap

except:
exitcode = 1
import traceback
sys.stderr.write('Process %s:\n' % self.name)
sys.stderr.flush()
traceback.print_exc()

Append a "sys.stderr.flush()" to the suite.

It surprised me that flushing was even necessary. I would've thought that the 
standard streams would all be closed just before the process terminated, 
regardless of exit status. But I observe that unless I explicitly flush stdout 
and stderr before terminating, the output is lost entirely, even if the exit is 
not abnormal. This isn't the desired behavior, is it?

--
components: Library (Lib)
messages: 151508
nosy: brandj
priority: normal
severity: normal
status: open
title: multiprocessing package doesn't flush stderr on child exception
type: behavior
versions: Python 3.2, Python 3.3, Python 3.4

___
Python tracker 
<http://bugs.python.org/issue13812>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13812] multiprocessing package doesn't flush stderr on child exception

2012-01-17 Thread Jon Brandvein

Jon Brandvein  added the comment:

(Er, that should be /Lib/multiprocessing/process.py :: Process._bootstrap of 
course.)

--

___
Python tracker 
<http://bugs.python.org/issue13812>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13812] multiprocessing package doesn't flush stderr on child exception

2012-01-22 Thread Jon Brandvein

Jon Brandvein  added the comment:

On Windows, the problem appears under Python 3.2.2 and 3.1.3, but not under 
2.7.1. On Linux, I have not reproduced the problem on versions 2.6.3, 2.7.2, 
3.1.1, or 3.2.2.

So to summarize:

  - It seems there should be a stderr flush call on the line I indicated, for 
symmetry with the surrounding code.
  - Even without this line, it should still be flushed automatically upon child 
process exit, but this doesn't happen under Windows and Python 3.x.

--

___
Python tracker 
<http://bugs.python.org/issue13812>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13812] multiprocessing package doesn't flush stderr on child exception

2012-01-22 Thread Jon Brandvein

Jon Brandvein  added the comment:

I've been looking over this package some more, and in particular, 
/Lib/multiprocessing/forking.py. There's plenty I don't understand, and I do 
have questions, if you would be willing to indulge me.

I see that both the unix and windows codepaths define an "exit" alias for 
terminating the child process without performing any cleanup. On unix, this is 
os._exit (though it calls it directly in Popen.__init__() instead of using the 
alias). On Windows, it is the win32 ExitProcess() function. A quick check 
confirms that replacing this windows alias with "exit = sys.exit" causes 
flushing to occur.

So my main question is: What's wrong with using sys.exit()? I would speculate 
it's either because there's shared state between child and parent, or to avoid 
propagating SystemExit through user code in the case freeze_support() was used.

If forking.py is to terminate directly via the OS, I think it's forking.py's 
responsibility to flush stdout and stderr in main() on the Windows side, the 
way it does in Popen.__init__() on the unix side.

I also want to point out that the sys.exit() in freeze_support() is unreachable 
due to the exit() in main().

So it no longer surprises me that the output is not being flushed in Python 3 
under windows. What surprises me is that it *is* flushed in Python 2. I 
remember hearing something about differences between 2 and 3 in how they handle 
buffering, so I'm investigating this for my own curiosity.

Incidentally, Python 2 still flushes when I remove newlines from my output 
text, so line buffering doesn't seem to be impacting my observations.

--

___
Python tracker 
<http://bugs.python.org/issue13812>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13812] multiprocessing package doesn't flush stderr on child exception

2012-01-22 Thread Jon Brandvein

Jon Brandvein  added the comment:

Some more information: When I write to a new file created by open(), all 
versions flush correctly. However, if I reassign sys.stdout to that file, 
Python 3.x does not (again, under Windows). I wonder what it is that causes 
these other files to flush.

(Note: I am testing by calling time.sleep() and inspecting the output file 
during and after the pause.)

--

___
Python tracker 
<http://bugs.python.org/issue13812>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13812] multiprocessing package doesn't flush stderr on child exception

2012-01-22 Thread Jon Brandvein

Jon Brandvein  added the comment:

It turns out the file output was flushing due to garbage collection. When I 
created and held a global reference to it, it ceased to flush. Clearly, 
reassigning sys.stdout also held a reference to it. So it wasn't any kind of 
special sys.stdout-specific logic.

I tried using os.fsync to determine whether data was being saved in an OS-level 
buffer. But since the OS may be free to ignore fsync, it's kind of worthless 
for this purpose.

I also found that under Python 2.x, even a low-level exit like os._exit or 
multiprocessing.win32.ExitProcess, called from within a user-level function in 
the child, caused flushing.

My best guess is that
  1. Python 2.x is not buffering data at the Python level. I can't see how it 
could be and still flush it out when calling _exit().
  2. Python 3.x is buffering at the Python level, and the Python File object 
needs to be destroyed or explicitly flushed before the hard low-level exit() in 
forking.py.

The solutions I can think of for Python 3.x are:
  1. Replace "exit = win32.ExitProcess" with "exit = sys.exit". All outstanding 
file objects will be destroyed and flushed naturally as the interpreter is torn 
down.
  2. Add an explicit stdout/stderr flush where appropriate in forking.py and 
process.py, to ensure tracebacks get written and to match the unix behavior. 
Leave it to the user to worry about flushing their own streams.
  3. Continue to use win32.ExitProcess, but add some kind of mechanism for 
walking through all existing Python File objects and flushing/destroying them. 
This was a fleeting thought; it really amounts to reimplementing the behavior 
of destructing the Python interpreter.

I'd really like to hear if there are good reasons for why (1) isn't how it's 
done currently. I'd also like to hear an explanation of Python 2.x's buffering.

--

___
Python tracker 
<http://bugs.python.org/issue13812>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13812] multiprocessing package doesn't flush stderr on child exception

2012-01-23 Thread Jon Brandvein

Jon Brandvein  added the comment:

Regarding the patch: I'd also like to see sys.stdout.flush() and 
sys.stderr.flush() between "exitcode = self._boostrap()" and "exit(exitcode)" 
in /Lib/multiprocessing/forking.py :: main(). (The extra stderr flush would be 
for symmetry with Popen.__init__() for unix.)

The remainder of this post is what I wrote before seeing your patch.


Thank you for the explanation concerning libc and buffering.

As for os._exit, I can see the need under unix, where the child process has a 
stack inherited from the parent. Also, allowing the child to cleanup shared 
resources would be disastrous for the parent. (I was going to propose the idea 
of making a sys.exit()-like function that did not rely on the exception 
mechanism to unwind the stack. But it wouldn't be usable here for this reason.)

Under Windows, the child process's multiprocessing.forking.main() is launched 
either by directly calling main() on the command line, or from within 
freeze_support() in the user program. In the latter case, the user can be 
advised not to catch SystemExit around freeze_support(), just as they are 
already advised to make calling freeze_support() the first statement within "if 
__name__ == '__main__':". So I don't see any harm in switching to sys.exit() 
there.


I think that in general, the differences between multiprocessing's behavior 
under unix and windows are a weakness, as is the lack of a precise 
specification for this behavior.

At the same time, multiprocessing is a lot more convenient to use than the 
subprocess module when the child process is a Python program. In particular, I 
use multiprocessing for its support of passing pickled objects between parent 
and child. With subprocess, I don't think it's even possible to share a file 
descriptor between parent and child under Windows.

I'm wondering whether it would be desirable to make an option for the unix side 
of multiprocessing to behave more like the windows one, and invoke the Python 
interpreter from the beginning with no trace of the parent's stack. That is, 
it'd follow a more traditional fork()-then-exec*() pattern. Then you'd be able 
to have the interpreter destruct naturally under both platforms, close 
resources, etc.

Are there use cases that require just forking under unix? Is the performance 
significantly better without an exec*()?

Perhaps it would be better If I took this discussion to python-ideas.

--

___
Python tracker 
<http://bugs.python.org/issue13812>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13841] multiprocessing should use sys.exit() where possible

2012-01-23 Thread Jon Brandvein

New submission from Jon Brandvein :

Currently the multiprocessing library calls a hard exit function (os._exit 
under unix, ExitProcess under Windows) to terminate the child process.

Under unix, this is necessary because the child is forked without exec-ing. 
Calling sys.exit() would make it possible for the child to run code on the part 
of the stack inherited from the parent, via the exception handling mechanism. 
It might also allow the child to accidentally destroy shared state through an 
object destructor, even when that object was not explicitly relied on by the 
child.

Under Windows, I do not see any benefit besides symmetry. Processes are not 
forked, and the only way control can pass to user code after executing the 
target function, is if the process is frozen and the user puts the call to 
freeze_support() inside a try block. This special case can be taken care of by 
advising the user not to do that. (We already tell the user where 
freeze_support() should be located.)

Changing the multiprocessing exit routine from ExitProcess to sys.exit on 
Windows would ensure that all objects holding resources get properly destroyed. 
In particular, it would ensure that all file streams (including standard output 
and standard error) are flushed. This is especially important under Python 3, 
since the new IO system uses its own buffering which cannot be flushed by 
ExitProcess -- from the user's point of view, a potential regression from 
Python 2.x.

Related issues:
  - #13812 would not have been a problem under windows.
  - If #8713 gets adopted, unix can use sys.exit() as well.

--
components: Library (Lib)
messages: 151835
nosy: brandj, jnoller, neologix, pitrou
priority: normal
severity: normal
status: open
title: multiprocessing should use sys.exit() where possible
type: enhancement
versions: Python 3.2, Python 3.3

___
Python tracker 
<http://bugs.python.org/issue13841>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13812] multiprocessing package doesn't flush stderr on child exception

2012-01-24 Thread Jon Brandvein

Jon Brandvein  added the comment:

Patch looks fine. I like the use of "finally" for the flush.

--

___
Python tracker 
<http://bugs.python.org/issue13812>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13841] multiprocessing should use sys.exit() where possible

2012-01-24 Thread Jon Brandvein

Jon Brandvein  added the comment:

Good point. I don't think those particular behaviors are documented, so I'm not 
sure whether we need to worry about breaking them.

--

___
Python tracker 
<http://bugs.python.org/issue13841>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13853] SystemExit/sys.exit() doesn't print boolean argument

2012-01-24 Thread Jon Brandvein

New submission from Jon Brandvein :

Raising SystemExit manually, or calling sys.exit, with an argument of "True" or 
"False" results in no output to the screen. According to 
Doc/library/exceptions.rst and Doc/library/sys.rst, any object that is not an 
integer or None should be printed to stderr.

Also, I'm not sure whether this is a bug, but "raise SystemExit(None)" differs 
from "sys.exit(None)", in that the former produces an exception with an args 
tuple of "(None,)", and the latter produces one with an empty args tuple.

--
components: Interpreter Core
messages: 151920
nosy: brandj
priority: normal
severity: normal
status: open
title: SystemExit/sys.exit() doesn't print boolean argument
type: behavior
versions: Python 2.7, Python 3.1, Python 3.2

___
Python tracker 
<http://bugs.python.org/issue13853>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13854] multiprocessing: SystemExit from child with non-int, non-str arg causes TypeError

2012-01-24 Thread Jon Brandvein

New submission from Jon Brandvein :

In a child process, raising SystemExit or calling sys.exit with a non-integer, 
non-string argument value causes a TypeError at Lib/multiprocessing/process.py 
:: _bootstrap. This is from concatenating the argument with '\n' and writing it 
to stderr.

Suggested fix: replace
sys.stderr.write(e.args[0] + '\n')
with
sys.stderr.write(str(e.args[0]) + '\n')

This problem also occurs when the value is None, but only for raising 
SystemExit (not calling sys.exit()).

--
components: Library (Lib)
messages: 151921
nosy: brandj, jnoller
priority: normal
severity: normal
status: open
title: multiprocessing: SystemExit from child with non-int, non-str arg causes 
TypeError
type: behavior
versions: Python 2.7, Python 3.1, Python 3.2

___
Python tracker 
<http://bugs.python.org/issue13854>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13857] Add textwrap.indent() as counterpart to textwrap.dedent()

2012-01-25 Thread Jon Brandvein

Jon Brandvein  added the comment:

> If such a function is added, I'd like the option to not indent empty lines: 
> trailing spaces are often not a good idea.

>From dedent's documentation, it wasn't immediately clear to me that it ignores 
>blank lines when determining common whitespace. (In fact the comment in the 
>example suggests otherwise.) Perhaps a note could be added to the 
>documentation when this change is made?

--
nosy: +brandj

___
Python tracker 
<http://bugs.python.org/issue13857>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue13854] multiprocessing: SystemExit from child with non-int, non-str arg causes TypeError

2012-01-25 Thread Jon Brandvein

Jon Brandvein  added the comment:

Also, as Brett pointed out to me in #13853, bool is a subclass of int, so they 
should follow the same code path. I suggest replacing

elif type(e.args[0]) is int:
exitcode = e.args[0]

with something like

elif isinstance(e.args[0], int):
exitcode = e.args[0]

which assumes that a subtype of int is convertible to int.

--

___
Python tracker 
<http://bugs.python.org/issue13854>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue10482] subprocess and deadlock avoidance

2012-02-05 Thread Jon Brandvein

Changes by Jon Brandvein :


--
nosy: +brandj

___
Python tracker 
<http://bugs.python.org/issue10482>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue4806] Function calls taking a generator as star argument can mask TypeErrors in the generator

2012-02-27 Thread Jon Brandvein

Changes by Jon Brandvein :


--
nosy: +brandj

___
Python tracker 
<http://bugs.python.org/issue4806>
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue21366] Document that return in finally overwrites prev value

2014-04-27 Thread Jon Brandvein

New submission from Jon Brandvein:

def foo():
try:
  return 1
finally;
  return 2
  print(foo())  # 2

I've seen this peculiar case discussed on a few blogs lately, but was unable to 
find confirmation that this behavior is defined.

In the try/finally section of Doc/reference/compound_stmts.rst, immediately 
after the sentence beginning

> When a return, break, or continue statement is executed

I propose adding something to the effect of:

> A return statement in a finally clause overrides the value of any return 
> statement executed in the try suite.

This wording also handles the case of nested try/finally blocks.

--
assignee: docs@python
components: Documentation
messages: 217277
nosy: brandjon, docs@python
priority: normal
severity: normal
status: open
title: Document that return in finally overwrites prev value
type: behavior

___
Python tracker 
<http://bugs.python.org/issue21366>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue24948] Multiprocessing not timely flushing stack trace to stderr

2015-08-27 Thread Jon Brandvein

Changes by Jon Brandvein :


--
nosy: +brandjon

___
Python tracker 
<http://bugs.python.org/issue24948>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com