[Python-Dev] PEP 475 accepted

Victor Stinner victor.stinner at gmail.com
Mon Feb 2 22:46:53 CET 2015


2015-02-02 22:11 GMT+01:00 Giampaolo Rodola' <g.rodola at gmail.com>:
> I may be chiming in a little late, however, I'd have a question: does this
> affect non-blocking applications somehow?
> How often should we expect to receive EINTR?

Each time a program is interrupted by a signal while it was waiting
for a sycall. Most syscalls are fast, especially in an application
written with non blocking operations.

For example, timeit says that os.getuid() takes 370 nanoseconds (on
Linux). getpid() only takes 285 nanoseconds, but it looks to be cached
in the libc: strace doesn't show me syscalls.

Network syscalls are probably slower.

haypo at selma$ ./python -Wignore -m timeit -s 'import socket;
s,c=socket.socketpair()' 's.send(b"a"); c.recv(1)'
100000 loops, best of 3: 2.26 usec per loop

> Is it correct to state that in case many EINTR signals are sent
> repeatedly a non-blocking framework such as asyncio may hang for "too long"?

A syscall fails with EINTR each time it gets a signal. You are
unlikely if the same syscall requires to be retried twice (executed 3
times) because it got EINTR twice.

I don't see why the kernel would make a syscall fails EINTR multiple times.

asyncio doesn't process the signal immediatly. asyncio uses
signal.set_wakeup_fd(). At the C level, the C signal handler writes
the signal number into a pipe. At the Python level, the selector is
awaken by the write. Later, asyncio executes the Python handler of the
signal (if a Python signal handler was registered).

A nice side effect of the PEP is to avoid to awake the application if
it's not necessary. If no Python signal handler is registered, no byte
is written into the pipe, the selector continues to wait for events.

Victor


More information about the Python-Dev mailing list