[issue14000] Subprocess stdin.flush does not flush

2012-02-13 Thread Andrew Moffat

New submission from Andrew Moffat :

The following code only works if the "p.stdin.close()" line is uncommented.  It 
seems that stdin only flushes to the process on stdin.close(), not on 
stdin.flush().

---

import subprocess as subp
import threading
import time


p = subp.Popen(["tr", "[:lower:]", "[:upper:]"],
stdin=subp.PIPE, stderr=subp.PIPE, stdout=subp.PIPE, close_fds=True)


def read(stdout):
while True:
line = stdout.readline()
if not line: break
print(line.decode("utf8"))

t = threading.Thread(target=read, args=(p.stdout,))
t.daemon = True
t.start()

p.stdin.write("uppercase\n".encode())
p.stdin.flush()
#p.stdin.close()

time.sleep(1)

--
components: None
messages: 153257
nosy: amoffat
priority: normal
severity: normal
status: open
title: Subprocess stdin.flush does not flush
type: behavior
versions: Python 2.7, Python 3.1, Python 3.2

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



[issue15898] OSX TTY bug

2012-09-09 Thread Andrew Moffat

New submission from Andrew Moffat:

I'm getting some kind of race condition on OSX when trying to read the output 
from a pseudoterminal of a forked process.  This race conditional only occurs 
if I run tty.tcsetattr on the master side of the pty, regardless of if I 
actually change the mode or not.

Try running the following code on OSX multiple times.  Sometimes you'll see 
"testing", sometimes you won't, sometimes it hangs.  If you comment out 
"tty.tcsetattr", you will consistently see "testing".


import os
import pty
import resource
import signal
import tty


master, slave = pty.openpty()
pid = os.fork()


# BUG IS HERE
# we're not making any changes to the tty mode, but
# the mere act of setting a mode causes the output to only
# show up sometimes.
#
# comment out "tty.tcsetattr" and the bug goes away
mode = tty.tcgetattr(master)
tty.tcsetattr(master, tty.TCSANOW, mode)


# child process
if pid == 0:
os.setsid()
os.close(master)

os.dup2(slave, 0)
os.dup2(slave, 1)
os.dup2(slave, 2)

max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
os.closerange(3, max_fd)

# make controlling terminal.  taken from pty.fork
tmp_fd = os.open(os.ttyname(1), os.O_RDWR)
os.close(tmp_fd)

os.write(1, "testing".encode())

os._exit(255)

# parent process
else:
os.close(slave)

try:
print(os.read(master, 1024))

finally:
os.kill(pid, signal.SIGKILL)

--
messages: 170147
nosy: amoffat
priority: normal
severity: normal
status: open
title: OSX TTY bug
type: behavior
versions: Python 2.6, Python 2.7, Python 3.1, Python 3.2

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



[issue15898] OSX TTY bug

2012-09-09 Thread Andrew Moffat

Andrew Moffat added the comment:

If I move tcsetattr into the parent, the race condition still exists.  If I 
move it into the child, before the write(), it works.

My environment is OSX 10.7.2 inside of Virtualbox (maybe this is the problem?)

I've shuffled some code around, and found case that fails consistently in 
python 3, but succeeds consistently on python 2.7.  It doesn't use tcsetattr at 
all, which is making me realize the problem may be deeper than I originally 
thought.  Are you able to confirm this, Ned?


import os
import pty
import resource
import signal
import tty
import time


master, slave = pty.openpty()
pid = os.fork()



# child process
if pid == 0:
os.setsid()
os.close(master)

os.dup2(slave, 0)
os.dup2(slave, 1)
os.dup2(slave, 2)

max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
os.closerange(3, max_fd)

# make controlling terminal.  taken from pty.fork
tmp_fd = os.open(os.ttyname(1), os.O_RDWR)
os.close(tmp_fd)

os.write(1, "testing".encode())

os._exit(255)

# parent process
else:
time.sleep(0.5)
os.close(slave)

try:
print(os.read(master, 1024))

finally:
os.kill(pid, signal.SIGKILL)

--

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



[issue15898] OSX TTY bug

2012-09-10 Thread Andrew Moffat

Andrew Moffat added the comment:

@Ned, Ok, give me a little time to work up those suggestions.  On my machine, 
the previous script prints "testing" consistently on 2.7, "" consistently on 
3.2.  I guess this is the behavior that is unexpected...it should print the 
same thing for both versions.  But if you are unable to confirm it, that's no 
good.  Let me work on this a little more before you guys close this.

@Martin, Thanks for the tip.

--

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



[issue15898] OSX TTY bug

2012-09-10 Thread Andrew Moffat

Andrew Moffat added the comment:

Below I attached a script that reproduces the behavior of an assertion error on 
a specific fork condition for a process with a pty.  Here are the results

Xubuntu x64:
   Python 2.7, parent_close_slave_before_child_write = False: WORKS
   Python 2.7, parent_close_slave_before_child_write = True: WORKS
   Python 3.2, parent_close_slave_before_child_write = False: WORKS
   Python 3.2, parent_close_slave_before_child_write = True: WORKS
Mac OSX 10.7.2:
   Python 2.7, parent_close_slave_before_child_write = False: WORKS
   Python 2.7, parent_close_slave_before_child_write = True: WORKS
   Python 3.2, parent_close_slave_before_child_write = False: >> FAILS <<
   Python 3.2, parent_close_slave_before_child_write = True: WORKS



Here's dtruss -f for python 2.7 and 3.0 on Mac OSX:

2.7, parent_close_slave_before_child_write = False (WORKS)

PID/THRD  SYSCALL(args)  = return
  356/0xc4a:  open_nocancel("/dev/ptmx\0", 0x20002, 0x0) = 3 0
  356/0xc4a:  ioctl(0x3, 0x20007454, 0x) = 0 0
  356/0xc4a:  ioctl(0x3, 0x20007452, 0x0)= 0 0
  356/0xc4a:  ioctl(0x3, 0x40807453, 0x10041AD20)= 0 0
  356/0xc4a:  stat64("/dev/ttys003\0", 0x7FFF5FBFF030, 0x0)  = 0 0
  356/0xc4a:  open_nocancel("/dev/ttys003\0", 0x20002, 0x0)  = 4 0
  356/0xc4a:  fork() = 362 0
  362/0xc61:  fork() = 0 0
  362/0xc61:  thread_selfid(0x100420BE0, 0x3, 0x1)   = 3169 0
  362/0xc61:  getpid(0x100420BE0, 0x3, 0x0)  = 362 0
  362/0xc61:  select(0x0, 0x0, 0x0, 0x0, 0x7FFF5FBFF3C0) = 0 0
  362/0xc61:  setsid(0x0, 0x0, 0x1001A7B40)  = 362 0
  362/0xc61:  close(0x3) = 0 0
  362/0xc61:  dup2(0x4, 0x0, 0x0)= 0 0
  362/0xc61:  dup2(0x4, 0x1, 0x0)= 1 0
  362/0xc61:  dup2(0x4, 0x2, 0x0)= 2 0
  362/0xc61:  getrlimit(0x1008, 0x7FFF5FBFF3D0, 0x0) = 0 0

  ... close range ...

  362/0xc61:  ioctl(0x1, 0x40487413, 0x7FFF5FBFF360) = 0 0
  362/0xc61:  fstat64(0x1, 0x7FFF5FBFF2D0, 0x0)  = 0 0
  362/0xc61:  open_nocancel("/dev/\0", 0x14, 0x0)= 3 0
  362/0xc61:  fcntl_nocancel(0x3, 0x2, 0x1)  = 0 0
  362/0xc61:  fstatfs64(0x3, 0x7FFF5FBFE7B0, 0x0)= 0 0
  362/0xc61:  getdirentries64(0x3, 0x1010AB600, 0x1000)  = 3080 0

  ... lots of lstat64 ...

  362/0xc61:  close_nocancel(0x3)= 0 0
  362/0xc61:  open("/dev/ttys003\0", 0x2, 0x1FF) = 3 0
  362/0xc61:  close(0x3) = 0 0
  362/0xc61:  write(0x1, "testing\0", 0x7)   = 7 0
  362/0xc61:  close(0x1) = 0 0
  356/0xc4a:  select(0x0, 0x0, 0x0, 0x0, 0x7FFF5FBFF3C0) = 0 0
  356/0xc4a:  close(0x4) = 0 0
  356/0xc4a:  read(0x3, "testing\0", 0x400)  = 7 0
  356/0xc4a:  write_nocancel(0x1, "'testing'\n\0", 0xA)  = 10 0
  356/0xc4a:  wait4(0x16A, 0x7FFF5FBFF3D4, 0x0)  = 362 0
  356/0xc4a:  sigaction(0x2, 0x7FFF5FBFF800, 0x7FFF5FBFF830) = 0 0


3.0, parent_close_slave_before_child_write = False (FAILS)

PID/THRD  SYSCALL(args)  = return
  385/0xe53:  open_nocancel("/dev/ptmx\0", 0x20002, 0xD15EB8)= 3 0
  385/0xe53:  ioctl(0x3, 0x20007454, 0xB1BC) = 0 0
  385/0xe53:  ioctl(0x3, 0x20007452, 0xB1BC) = 0 0
  385/0xe53:  ioctl(0x3, 0x40807453, 0x64F220)   = 0 0
  385/0xe53:  stat64("/dev/ttys003\0", 0xB164, 0x64F220) = 0 0
  385/0xe53:  open_nocancel("/dev/ttys003\0", 0x20002, 0x0)  = 4 0
  385/0xe53:  fork() = 389 0
  389/0xe5c:  fork() = 0 0
  389/0xe5c:  thread_selfid(0x0, 0x0, 0x0)   = 3676 0
  389/0xe5c:  getpid(0x0, 0x0, 0x0)  = 389 0
  389/0xe5c:  select_nocancel(0x0, 0x0, 0x0) = 0 0
  389/0xe5c:  setsid(0x0, 0x0, 0x0)  = 389 0
  389/0xe5c:  close_nocancel(0x3)= 0 0
  389/0xe5c:  dup2(0x4, 0x0, 0x0)= 0 0
  389/0xe5c:  dup2(0x4, 0x1, 0x0)= 1 0
  389/0xe5c:  dup2(0x4, 0x2, 0x0)= 2 0
  389/0xe5c:  getrlimit(0x8, 0xB46C, 0x0)= 0 0

  ... close range ...

  389/0xe5c:  ioctl(0x1, 0x402C7413, 0xB410) = 0 0
  389/0xe5c:  fstat64(0x1, 0xB3A4, 0xB410)   = 0 0
  389/0xe5c:  open_nocancel("/dev/\0", 0x14, 0xBFFFE968) = 3 0
  389/0xe5c:  fcntl_nocancel(0x3, 0x2, 0x1)  = 0 0
  389/0xe5c:  fstatfs64(0x3, 0xBFFFE8D8, 0x1)= 0 0
  389/0xe5c:  getdirentries64(0x3, 0x10DFC00, 0x1000)= 3080 0

  ... lots of lstat64 ...

  389/0xe5c:  close_nocancel(0x3)= 0 0
  389/0xe5c:  open_nocancel("/dev/ttys003\0", 0x20002, 0x0)  = 3 0
  389/0xe5c:  close_nocancel(0x3)= 0 0
  389/0xe5c:  write_nocancel(0x1, "testing\0", 0x7)  = 7 0
  389/0xe5c:  close_nocancel(0x1)= 0 0
  385/0xe53:  select_nocancel(0x0, 0x0, 0x0) = 0 0
  385/0xe53:  close_nocancel(0x4)= 0 0
  385/0xe53:  read_noca

[issue15898] OSX TTY bug

2012-09-11 Thread Andrew Moffat

Andrew Moffat added the comment:

Sorry about that, I refactored out the string at the last minute and typed 
"testing123" instead of the original "testing" from the trace.

I'm not sure I follow the problem exactly.  So you're saying that the failing 
version uses _cancel sys calls, and that __pthread_testcancel may result in 
EINTR.  But that this is not happening in the trace, and data is being written 
successfully.  I guess I'm wondering where the written bytes went and if 
there's any way to retrieve them?

--

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