[issue32345] EIO from write() is only fatal if print() contains a newline

Creideiki report at bugs.python.org
Wed Dec 20 06:09:59 EST 2017


Creideiki <creideiki+pythonbugs at ferretporn.se> added the comment:

Hmm. Yes and no; you seem to be correct in that the problem is on the libc level, but Python definitely does something special.

By the way, this is glibc 2.26.

I tried this C program:

#include <stdio.h>
#include <unistd.h>

int main()
{
   usleep(5 * 1000 * 1000);
   fwrite("A", 1, 1, stdout);
   perror("A");
   fwrite("\n", 1, 1, stdout);
   perror("newline 1");
   fwrite("B\nC", 3, 1, stdout);
   perror("BC");
   fwrite("\n", 1, 1, stdout);
   perror("newline 2");
   fwrite("D", 1, 1, stdout);
   perror("D");
   fwrite("\n", 1, 1, stdout);
   perror("newline 3");
   return 0;
}

Which behaves similarly when there's a newline in the middle of the string, in that fwrite() returns with an error after writing the newline:

write(3, "A: Success\n", 11)            = -1 EIO (Input/output error)
write(1, "A\n", 2)                      = -1 EIO (Input/output error)
write(3, "newline 1: Input/output error\n", 30) = -1 EIO (Input/output error)
write(1, "B\n", 2)                      = -1 EIO (Input/output error)
write(3, "BC: Input/output error\n", 23) = -1 EIO (Input/output error)
write(1, "\n", 1)                       = -1 EIO (Input/output error)
write(3, "newline 2: Input/output error\n", 30) = -1 EIO (Input/output error)
write(3, "D: Input/output error\n", 22) = -1 EIO (Input/output error)
write(1, "D\n", 2)                      = -1 EIO (Input/output error)
write(3, "newline 3: Input/output error\n", 30) = -1 EIO (Input/output error)

However, as can be seen from the result of the perror() calls, every fwrite() after the first buffer flush (which happens on newlines, since stdout to a terminal is line buffered) fails with EIO. This should mean that, at the latest, the second Python print() call should fail. But it doesn't:

#!/bin/env python2.7
import time
time.sleep(5)
print('A')
print('E')
print('B\nC')
print('D')

write(1, "A\n", 2)                      = -1 EIO (Input/output error)
write(1, "E\n", 2)                      = -1 EIO (Input/output error)
write(1, "B\n", 2)                      = -1 EIO (Input/output error)
write(2, "Traceback (most recent call last):\n", 35) = -1 EIO (Input/output error)
write(2, "  File \"./fatal.py\", line 6, in <module>\n", 41) = -1 EIO (Input/output error)

So Python does make a difference between the implicit newline added to the end of each print() and a newline in the middle of the user-supplied string.

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue32345>
_______________________________________


More information about the Python-bugs-list mailing list