Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
3c7d6e06
Kaydet (Commit)
3c7d6e06
authored
Mar 30, 2015
tarafından
Victor Stinner
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #23485: select.poll.poll() is now retried when interrupted by a signal
üst
fa09beb1
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
112 additions
and
62 deletions
+112
-62
select.rst
Doc/library/select.rst
+6
-0
3.5.rst
Doc/whatsnew/3.5.rst
+1
-1
asyncore.py
Lib/asyncore.py
+2
-4
selectors.py
Lib/selectors.py
+3
-4
eintr_tester.py
Lib/test/eintrdata/eintr_tester.py
+17
-3
selectmodule.c
Modules/selectmodule.c
+83
-50
No files found.
Doc/library/select.rst
Dosyayı görüntüle @
3c7d6e06
...
@@ -408,6 +408,12 @@ linearly scanned again. :c:func:`select` is O(highest file descriptor), while
...
@@ -408,6 +408,12 @@ linearly scanned again. :c:func:`select` is O(highest file descriptor), while
returning. If *timeout* is omitted, negative, or :const:`None`, the call will
returning. If *timeout* is omitted, negative, or :const:`None`, the call will
block until there is an event for this poll object.
block until there is an event for this poll object.
.. versionchanged:: 3.5
The function is now retried with a recomputed timeout when interrupted by
a signal, except if the signal handler raises an exception (see
:pep:`475` for the rationale), instead of raising
:exc:`InterruptedError`.
.. _kqueue-objects:
.. _kqueue-objects:
...
...
Doc/whatsnew/3.5.rst
Dosyayı görüntüle @
3c7d6e06
...
@@ -621,7 +621,7 @@ Changes in the Python API
...
@@ -621,7 +621,7 @@ Changes in the Python API
- :func:`os.open`, :func:`open`
- :func:`os.open`, :func:`open`
- :func:`os.read`, :func:`os.write`
- :func:`os.read`, :func:`os.write`
- :func:`select.select`
- :func:`select.select`
, :func:`select.poll.poll`
- :func:`time.sleep`
- :func:`time.sleep`
* Before Python 3.5, a :class:`datetime.time` object was considered to be false
* Before Python 3.5, a :class:`datetime.time` object was considered to be false
...
...
Lib/asyncore.py
Dosyayı görüntüle @
3c7d6e06
...
@@ -179,10 +179,8 @@ def poll2(timeout=0.0, map=None):
...
@@ -179,10 +179,8 @@ def poll2(timeout=0.0, map=None):
flags
|=
select
.
POLLOUT
flags
|=
select
.
POLLOUT
if
flags
:
if
flags
:
pollster
.
register
(
fd
,
flags
)
pollster
.
register
(
fd
,
flags
)
try
:
r
=
pollster
.
poll
(
timeout
)
r
=
pollster
.
poll
(
timeout
)
except
InterruptedError
:
r
=
[]
for
fd
,
flags
in
r
:
for
fd
,
flags
in
r
:
obj
=
map
.
get
(
fd
)
obj
=
map
.
get
(
fd
)
if
obj
is
None
:
if
obj
is
None
:
...
...
Lib/selectors.py
Dosyayı görüntüle @
3c7d6e06
...
@@ -359,11 +359,10 @@ if hasattr(select, 'poll'):
...
@@ -359,11 +359,10 @@ if hasattr(select, 'poll'):
# poll() has a resolution of 1 millisecond, round away from
# poll() has a resolution of 1 millisecond, round away from
# zero to wait *at least* timeout seconds.
# zero to wait *at least* timeout seconds.
timeout
=
math
.
ceil
(
timeout
*
1e3
)
timeout
=
math
.
ceil
(
timeout
*
1e3
)
fd_event_list
=
self
.
_poll
.
poll
(
timeout
)
ready
=
[]
ready
=
[]
try
:
fd_event_list
=
self
.
_poll
.
poll
(
timeout
)
except
InterruptedError
:
return
ready
for
fd
,
event
in
fd_event_list
:
for
fd
,
event
in
fd_event_list
:
events
=
0
events
=
0
if
event
&
~
select
.
POLLIN
:
if
event
&
~
select
.
POLLIN
:
...
...
Lib/test/eintrdata/eintr_tester.py
Dosyayı görüntüle @
3c7d6e06
...
@@ -38,8 +38,12 @@ class EINTRBaseTest(unittest.TestCase):
...
@@ -38,8 +38,12 @@ class EINTRBaseTest(unittest.TestCase):
cls
.
signal_period
)
cls
.
signal_period
)
@classmethod
@classmethod
def
tearDownClass
(
cls
):
def
stop_alarm
(
cls
):
signal
.
setitimer
(
signal
.
ITIMER_REAL
,
0
,
0
)
signal
.
setitimer
(
signal
.
ITIMER_REAL
,
0
,
0
)
@classmethod
def
tearDownClass
(
cls
):
cls
.
stop_alarm
()
signal
.
signal
(
signal
.
SIGALRM
,
cls
.
orig_handler
)
signal
.
signal
(
signal
.
SIGALRM
,
cls
.
orig_handler
)
@classmethod
@classmethod
...
@@ -260,7 +264,7 @@ class TimeEINTRTest(EINTRBaseTest):
...
@@ -260,7 +264,7 @@ class TimeEINTRTest(EINTRBaseTest):
def
test_sleep
(
self
):
def
test_sleep
(
self
):
t0
=
time
.
monotonic
()
t0
=
time
.
monotonic
()
time
.
sleep
(
self
.
sleep_time
)
time
.
sleep
(
self
.
sleep_time
)
s
ignal
.
alarm
(
0
)
s
elf
.
stop_alarm
(
)
dt
=
time
.
monotonic
()
-
t0
dt
=
time
.
monotonic
()
-
t0
self
.
assertGreaterEqual
(
dt
,
self
.
sleep_time
)
self
.
assertGreaterEqual
(
dt
,
self
.
sleep_time
)
...
@@ -311,7 +315,17 @@ class SelectEINTRTest(EINTRBaseTest):
...
@@ -311,7 +315,17 @@ class SelectEINTRTest(EINTRBaseTest):
def
test_select
(
self
):
def
test_select
(
self
):
t0
=
time
.
monotonic
()
t0
=
time
.
monotonic
()
select
.
select
([],
[],
[],
self
.
sleep_time
)
select
.
select
([],
[],
[],
self
.
sleep_time
)
signal
.
alarm
(
0
)
self
.
stop_alarm
()
dt
=
time
.
monotonic
()
-
t0
self
.
assertGreaterEqual
(
dt
,
self
.
sleep_time
)
@unittest.skipUnless
(
hasattr
(
select
,
'poll'
),
'need select.poll'
)
def
test_poll
(
self
):
poller
=
select
.
poll
()
t0
=
time
.
monotonic
()
poller
.
poll
(
self
.
sleep_time
*
1e3
)
self
.
stop_alarm
()
dt
=
time
.
monotonic
()
-
t0
dt
=
time
.
monotonic
()
-
t0
self
.
assertGreaterEqual
(
dt
,
self
.
sleep_time
)
self
.
assertGreaterEqual
(
dt
,
self
.
sleep_time
)
...
...
Modules/selectmodule.c
Dosyayı görüntüle @
3c7d6e06
...
@@ -279,6 +279,7 @@ select_select(PyObject *self, PyObject *args)
...
@@ -279,6 +279,7 @@ select_select(PyObject *self, PyObject *args)
break
;
break
;
}
}
_PyTime_AsTimeval_noraise
(
timeout
,
&
tv
,
_PyTime_ROUND_CEILING
);
_PyTime_AsTimeval_noraise
(
timeout
,
&
tv
,
_PyTime_ROUND_CEILING
);
/* retry select() with the recomputed timeout */
}
}
}
while
(
1
);
}
while
(
1
);
...
@@ -520,30 +521,39 @@ any descriptors that have events or errors to report.");
...
@@ -520,30 +521,39 @@ any descriptors that have events or errors to report.");
static
PyObject
*
static
PyObject
*
poll_poll
(
pollObject
*
self
,
PyObject
*
args
)
poll_poll
(
pollObject
*
self
,
PyObject
*
args
)
{
{
PyObject
*
result_list
=
NULL
,
*
t
out
=
NULL
;
PyObject
*
result_list
=
NULL
,
*
t
imeout_obj
=
NULL
;
int
timeout
=
0
,
poll_result
,
i
,
j
;
int
poll_result
,
i
,
j
;
PyObject
*
value
=
NULL
,
*
num
=
NULL
;
PyObject
*
value
=
NULL
,
*
num
=
NULL
;
_PyTime_t
timeout
,
ms
,
deadline
;
int
async_err
=
0
;
if
(
!
PyArg_
UnpackTuple
(
args
,
"poll"
,
0
,
1
,
&
tout
))
{
if
(
!
PyArg_
ParseTuple
(
args
,
"|O:poll"
,
&
timeout_obj
))
{
return
NULL
;
return
NULL
;
}
}
/* Check values for timeout */
/* Check values for timeout */
if
(
t
out
==
NULL
||
tout
==
Py_None
)
if
(
t
imeout_obj
==
NULL
||
timeout_obj
==
Py_None
)
{
timeout
=
-
1
;
timeout
=
-
1
;
else
if
(
!
PyNumber_Check
(
tout
))
{
ms
=
-
1
;
PyErr_SetString
(
PyExc_TypeError
,
deadline
=
0
;
"timeout must be an integer or None"
);
return
NULL
;
}
}
else
{
else
{
tout
=
PyNumber_Long
(
tout
);
if
(
_PyTime_FromMillisecondsObject
(
&
timeout
,
timeout_obj
,
if
(
!
tout
)
_PyTime_ROUND_CEILING
)
<
0
)
{
if
(
PyErr_ExceptionMatches
(
PyExc_TypeError
))
{
PyErr_SetString
(
PyExc_TypeError
,
"timeout must be an integer or None"
);
}
return
NULL
;
return
NULL
;
timeout
=
_PyLong_AsInt
(
tout
);
}
Py_DECREF
(
tout
);
if
(
timeout
==
-
1
&&
PyErr_Occurred
())
ms
=
_PyTime_AsMilliseconds
(
timeout
,
_PyTime_ROUND_CEILING
);
if
(
ms
<
INT_MIN
||
ms
>
INT_MAX
)
{
PyErr_SetString
(
PyExc_OverflowError
,
"timeout is too large"
);
return
NULL
;
return
NULL
;
}
deadline
=
_PyTime_GetMonotonicClock
()
+
timeout
;
}
}
/* Avoid concurrent poll() invocation, issue 8865 */
/* Avoid concurrent poll() invocation, issue 8865 */
...
@@ -561,14 +571,38 @@ poll_poll(pollObject *self, PyObject *args)
...
@@ -561,14 +571,38 @@ poll_poll(pollObject *self, PyObject *args)
self
->
poll_running
=
1
;
self
->
poll_running
=
1
;
/* call poll() */
/* call poll() */
Py_BEGIN_ALLOW_THREADS
async_err
=
0
;
poll_result
=
poll
(
self
->
ufds
,
self
->
ufd_len
,
timeout
);
do
{
Py_END_ALLOW_THREADS
Py_BEGIN_ALLOW_THREADS
errno
=
0
;
poll_result
=
poll
(
self
->
ufds
,
self
->
ufd_len
,
(
int
)
ms
);
Py_END_ALLOW_THREADS
if
(
errno
!=
EINTR
)
break
;
/* poll() was interrupted by a signal */
if
(
PyErr_CheckSignals
())
{
async_err
=
1
;
break
;
}
if
(
timeout
>=
0
)
{
timeout
=
deadline
-
_PyTime_GetMonotonicClock
();
if
(
timeout
<
0
)
{
poll_result
=
0
;
break
;
}
ms
=
_PyTime_AsMilliseconds
(
timeout
,
_PyTime_ROUND_CEILING
);
/* retry poll() with the recomputed timeout */
}
}
while
(
1
);
self
->
poll_running
=
0
;
self
->
poll_running
=
0
;
if
(
poll_result
<
0
)
{
if
(
poll_result
<
0
)
{
PyErr_SetFromErrno
(
PyExc_OSError
);
if
(
!
async_err
)
PyErr_SetFromErrno
(
PyExc_OSError
);
return
NULL
;
return
NULL
;
}
}
...
@@ -577,41 +611,40 @@ poll_poll(pollObject *self, PyObject *args)
...
@@ -577,41 +611,40 @@ poll_poll(pollObject *self, PyObject *args)
result_list
=
PyList_New
(
poll_result
);
result_list
=
PyList_New
(
poll_result
);
if
(
!
result_list
)
if
(
!
result_list
)
return
NULL
;
return
NULL
;
else
{
for
(
i
=
0
,
j
=
0
;
j
<
poll_result
;
j
++
)
{
for
(
i
=
0
,
j
=
0
;
j
<
poll_result
;
j
++
)
{
/* skip to the next fired descriptor */
/* skip to the next fired descriptor */
while
(
!
self
->
ufds
[
i
].
revents
)
{
while
(
!
self
->
ufds
[
i
].
revents
)
{
i
++
;
}
/* if we hit a NULL return, set value to NULL
and break out of loop; code at end will
clean up result_list */
value
=
PyTuple_New
(
2
);
if
(
value
==
NULL
)
goto
error
;
num
=
PyLong_FromLong
(
self
->
ufds
[
i
].
fd
);
if
(
num
==
NULL
)
{
Py_DECREF
(
value
);
goto
error
;
}
PyTuple_SET_ITEM
(
value
,
0
,
num
);
/* The &0xffff is a workaround for AIX. 'revents'
is a 16-bit short, and IBM assigned POLLNVAL
to be 0x8000, so the conversion to int results
in a negative number. See SF bug #923315. */
num
=
PyLong_FromLong
(
self
->
ufds
[
i
].
revents
&
0xffff
);
if
(
num
==
NULL
)
{
Py_DECREF
(
value
);
goto
error
;
}
PyTuple_SET_ITEM
(
value
,
1
,
num
);
if
((
PyList_SetItem
(
result_list
,
j
,
value
))
==
-
1
)
{
Py_DECREF
(
value
);
goto
error
;
}
i
++
;
i
++
;
}
}
/* if we hit a NULL return, set value to NULL
and break out of loop; code at end will
clean up result_list */
value
=
PyTuple_New
(
2
);
if
(
value
==
NULL
)
goto
error
;
num
=
PyLong_FromLong
(
self
->
ufds
[
i
].
fd
);
if
(
num
==
NULL
)
{
Py_DECREF
(
value
);
goto
error
;
}
PyTuple_SET_ITEM
(
value
,
0
,
num
);
/* The &0xffff is a workaround for AIX. 'revents'
is a 16-bit short, and IBM assigned POLLNVAL
to be 0x8000, so the conversion to int results
in a negative number. See SF bug #923315. */
num
=
PyLong_FromLong
(
self
->
ufds
[
i
].
revents
&
0xffff
);
if
(
num
==
NULL
)
{
Py_DECREF
(
value
);
goto
error
;
}
PyTuple_SET_ITEM
(
value
,
1
,
num
);
if
((
PyList_SetItem
(
result_list
,
j
,
value
))
==
-
1
)
{
Py_DECREF
(
value
);
goto
error
;
}
i
++
;
}
}
return
result_list
;
return
result_list
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment