New submission from Charles-François Natali:

After optimizing epoll() to use a per-instance buffer like poll() does 
(http://bugs.python.org/issue16876), I realized that it wasn't thread-safe, and 
can result in crashes:
"""
 ./python /tmp/test.py
*** glibc detected *** ./python: free(): corrupted unsorted chunks: 
0x0000000001c8e690 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3041c75676]
./python[0x4fd9ae]
./python(PyThreadState_DeleteCurrent+0x10c)[0x4fdb91]
./python[0x52a444]
/lib64/libpthread.so.0[0x30428077e1]
/lib64/libc.so.6(clone+0x6d)[0x3041ce153d]
======= Memory map: ========
[...]
"""

The problem is that poll (and now epoll) array is stored per-instance, and if 
second call to poll() is made while another thread is currently blocked on 
poll(), the array is reallocated (through PyMem_Resize()) if the buffer size 
has changed (if the number of FDs registered has changed).

"""
static int
update_ufd_array(pollObject *self)
[...]
    self->ufd_len = PyDict_Size(self->dict);
    PyMem_RESIZE(self->ufds, struct pollfd, self->ufd_len);
[...]
"""

can be called while another thread is blocked there:
"""
    /* call poll() */
    Py_BEGIN_ALLOW_THREADS
    poll_result = poll(self->ufds, self->ufd_len, timeout);
    Py_END_ALLOW_THREADS
"""

So when the first call to poll() returns, it can end up in SIGSEGV or heap 
corruption (unless the array was increased an realloc() was able to expand it 
in-place).

Reproducer script attached.

----------
components: Extension Modules
files: test.py
messages: 179647
nosy: christian.heimes, neologix
priority: normal
severity: normal
stage: needs patch
status: open
title: poll()/epoll() are not thread-safe
type: crash
versions: Python 2.7, Python 3.2, Python 3.3, Python 3.4
Added file: http://bugs.python.org/file28685/test.py

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue16929>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to