homepage

This issue tracker has been migrated to GitHub , and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: poll()/epoll() are not thread-safe
Type: crash Stage: needs patch
Components: Extension Modules Versions: Python 3.2, Python 3.3, Python 3.4, Python 2.7
process
Status: closed Resolution: duplicate
Dependencies: Superseder: select.poll is not thread safe
View: 8865
Assigned To: Nosy List: christian.heimes, neologix, serhiy.storchaka
Priority: normal Keywords:

Created on 2013年01月11日 08:36 by neologix, last changed 2022年04月11日 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
test.py neologix, 2013年01月11日 08:36
Messages (3)
msg179647 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2013年01月11日 08:36
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.
msg179653 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2013年01月11日 08:50
For poll() see issue8865.
msg179656 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2013年01月11日 08:58
OK, I'll close as duplicate.
History
Date User Action Args
2022年04月11日 14:57:40adminsetgithub: 61133
2013年01月11日 09:00:48neologixsetstatus: open -> closed
2013年01月11日 08:58:36neologixsetsuperseder: select.poll is not thread safe
dependencies: - select.poll is not thread safe
resolution: duplicate
messages: + msg179656
2013年01月11日 08:52:15serhiy.storchakasetdependencies: + select.poll is not thread safe
2013年01月11日 08:50:48serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg179653
2013年01月11日 08:36:44neologixcreate

AltStyle によって変換されたページ (->オリジナル) /