[issue41222] Undocumented behaviour change of POpen.stdout.readine with bufsize=0 or =1

2021-05-02 Thread Yann Dirson


Yann Dirson  added the comment:

With upcoming 3.10 phasing out 2.7 compatibility I have to find a solution to 
this, so I'm back digging here.

Even .read(1) on a subprocess pipe causes an underlying buffered read, so 
working around the problem by a loop of 1-byte reads has to do with os.read(), 
though its usage on file-like object is discouraged.

It looks like one of those would be needed, depending on the expected semantics 
of `POpen`'s `bufsize` parameter:

* use the provided bufsize for the underlying buffering
* provide a dummy pipe fd through fileno(), feeding it data as long as a read() 
call leaves data in the underlying buffer (indeed a simple conditional 1-byte 
read or write to the pipe before returning to caller should provide the correct 
semantics)

--
versions: +Python 3.9

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



[issue41222] Undocumented behaviour change of POpen.stdout.readine with bufsize=0 or =1

2021-05-03 Thread Yann Dirson


Yann Dirson  added the comment:

Relevant commits include this one from v3.1.4:

 commit 877766dee8e60c7971ed0cabba89fbe981c2ab1b
 Author: Antoine Pitrou 
 Date:   Sat Mar 19 17:00:37 2011 +0100

Issue #11459: A `bufsize` value of 0 in subprocess.Popen() really creates
unbuffered pipes, such that select() works properly on them.


I can't use that commit without cherry-picking this one from v3.2.2, though:

 commit e96ec6810184f5daacb2d47ab8801365c99bb206
 Author: Antoine Pitrou 
 Date:   Sat Jul 23 21:46:35 2011 +0200

Issue #12591: Allow io.TextIOWrapper to work with raw IO objects (without
a read1() method), and add an undocumented *write_through* parameter to
mandate unbuffered writes.


And my test script still shows the same behaviour, with poll.poll() or 
poll.select().

The fact that my stdout object has no read1() and needs the above patch looks 
like a good lead for further investigation?

--

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



[issue41222] Undocumented behaviour change of POpen.stdout.readine with bufsize=0 or =1

2021-05-03 Thread Yann Dirson


Change by Yann Dirson :


--
keywords: +patch
pull_requests: +24542
stage:  -> patch review
pull_request: https://github.com/python/cpython/pull/25859

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



[issue41222] POpen bufsize=0 ignored with universal_newlines=True

2021-05-03 Thread Yann Dirson


Yann Dirson  added the comment:

> The fact that my stdout object has no read1() and needs the above patch looks 
> like a good lead for further investigation?

That's linked to universal_newlines, the bug only shows when that flag is set.

Testcases provided in https://github.com/python/cpython/pull/25859

--
title: Undocumented behaviour change of POpen.stdout.readine with bufsize=0 or 
=1 -> POpen bufsize=0 ignored with universal_newlines=True

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



[issue41222] Undocumented behaviour change of POpen.stdout.readine with bufsize=0 or =1

2020-07-06 Thread Yann Dirson


New submission from Yann Dirson :

On a POpen object created with bufsize=0, stdout.readline() does a buffered 
reading with python3, whereas in 2.7 it did char-by-char reading.  See attached 
example.

As a result, a poll including the stdout object suffers a behaviour change when 
stdout is ready for writing and there is more than one line of data available.  
In both cases we get notified by poll() that data is available on the fd and we 
can stdout.readline() and get back to our polling loop.  Then:

* with python2 poll() then returns immediately and stdout.readline() will then 
return the next line

* with python3 poll() now blocks

Running the attached example under strace reveals the underlying difference:

 write(4, "go\n", 3) = 3
 poll([{fd=5, events=POLLIN|POLLERR|POLLHUP}], 1, -1) = 1 ([{fd=5, 
revents=POLLIN}])
-read(5, "x", 1) = 1
-read(5, "x", 1) = 1
-read(5, "x", 1) = 1
-read(5, "x", 1) = 1
-read(5, "x", 1) = 1
-read(5, "x", 1) = 1
-read(5, "x", 1) = 1
-read(5, "x", 1) = 1
-read(5, "x", 1) = 1
-read(5, "x", 1) = 1
-read(5, "x", 1) = 1
-read(5, "x", 1) = 1
-read(5, "\n", 1)= 1
-fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x2), ...}) = 0
+read(5, "\nyyy\naaa"..., 8192) = 74
 write(1, ">\n", 14) = 14


We can see a buffered read, which explains the behaviour difference.

Changing to bufsize=1, strace does not show a difference here.

This is especially troubling, as the first note in 
https://docs.python.org/3/library/io.html#class-hierarchy mentions that even in 
buffered mode there is an unoptimized readline() implementation.

--
components: IO
files: testproc-unbuffered.py
messages: 373165
nosy: yann
priority: normal
severity: normal
status: open
title: Undocumented behaviour change of POpen.stdout.readine with bufsize=0 or 
=1
type: behavior
versions: Python 3.5, Python 3.6, Python 3.7, Python 3.8
Added file: https://bugs.python.org/file49299/testproc-unbuffered.py

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