Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gevent
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
gevent
Commits
af8e9dac
Commit
af8e9dac
authored
Feb 14, 2018
by
Jason Madden
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Simplify libev default loop handling and let it regenerate itself.
parent
9bdd5317
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
63 additions
and
36 deletions
+63
-36
CHANGES.rst
CHANGES.rst
+5
-0
src/gevent/_ffi/loop.py
src/gevent/_ffi/loop.py
+9
-7
src/gevent/libev/corecext.pyx
src/gevent/libev/corecext.pyx
+9
-12
src/gevent/libev/corecffi.py
src/gevent/libev/corecffi.py
+10
-3
src/gevent/libev/libev.pxd
src/gevent/libev/libev.pxd
+2
-0
src/gevent/libuv/loop.py
src/gevent/libuv/loop.py
+4
-4
src/greentest/test__core.py
src/greentest/test__core.py
+22
-5
src/greentest/test__destroy.py
src/greentest/test__destroy.py
+2
-5
No files found.
CHANGES.rst
View file @
af8e9dac
...
@@ -64,6 +64,11 @@
...
@@ -64,6 +64,11 @@
extension implementation only) deallocated (garbage collected). See
extension implementation only) deallocated (garbage collected). See
:issue:`1098`.
:issue:`1098`.
- Simplify handling of the libev default loop and the ``destroy()``
method. The default loop, when destroyed, can again be requested and
it will regenerate itself. The default loop is the only one that can
receive child events.
1.3a1 (2018-01-27)
1.3a1 (2018-01-27)
==================
==================
...
...
src/gevent/_ffi/loop.py
View file @
af8e9dac
...
@@ -487,12 +487,11 @@ class AbstractLoop(object):
...
@@ -487,12 +487,11 @@ class AbstractLoop(object):
"""
"""
if
self
.
_ptr
:
if
self
.
_ptr
:
try
:
try
:
if
self
.
_default
:
if
not
self
.
_can_destroy_loop
(
self
.
_ptr
):
if
not
self
.
_can_destroy_default_loop
():
return
False
return
False
type
(
self
).
_default_loop_destroyed
=
True
self
.
_destroyed_loop
(
self
.
_ptr
)
self
.
_stop_aux_watchers
()
self
.
_stop_aux_watchers
()
finally
:
finally
:
# not ffi.NULL, we don't want something that can be
# not ffi.NULL, we don't want something that can be
# passed to C and crash later. This will create nice friendly
# passed to C and crash later. This will create nice friendly
...
@@ -501,8 +500,11 @@ class AbstractLoop(object):
...
@@ -501,8 +500,11 @@ class AbstractLoop(object):
return
True
return
True
def
_can_destroy_default_loop
(
self
):
def
_can_destroy_loop
(
self
,
ptr
):
return
not
type
(
self
).
_default_loop_destroyed
raise
NotImplementedError
()
def
_destroyed_loop
(
self
,
ptr
):
raise
NotImplementedError
()
@
property
@
property
def
ptr
(
self
):
def
ptr
(
self
):
...
...
src/gevent/libev/corecext.pyx
View file @
af8e9dac
...
@@ -259,8 +259,6 @@ cdef bint _check_loop(loop loop) except -1:
...
@@ -259,8 +259,6 @@ cdef bint _check_loop(loop loop) except -1:
return
1
return
1
cdef
bint
_default_loop_destroyed
=
False
cdef
public
class
callback
[
object
PyGeventCallbackObject
,
type
PyGeventCallback_Type
]:
cdef
public
class
callback
[
object
PyGeventCallbackObject
,
type
PyGeventCallback_Type
]:
cdef
public
object
callback
cdef
public
object
callback
...
@@ -419,8 +417,6 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
...
@@ -419,8 +417,6 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
c_flags
|=
libev
.
EVFLAG_FORKCHECK
c_flags
|=
libev
.
EVFLAG_FORKCHECK
if
default
is
None
:
if
default
is
None
:
default
=
True
default
=
True
if
_default_loop_destroyed
:
default
=
False
if
default
:
if
default
:
self
.
_default
=
1
self
.
_default
=
1
self
.
_ptr
=
libev
.
gevent_ev_default_loop
(
c_flags
)
self
.
_ptr
=
libev
.
gevent_ev_default_loop
(
c_flags
)
...
@@ -436,6 +432,8 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
...
@@ -436,6 +432,8 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
if
default
or
__SYSERR_CALLBACK
is
None
:
if
default
or
__SYSERR_CALLBACK
is
None
:
set_syserr_cb
(
self
.
_handle_syserr
)
set_syserr_cb
(
self
.
_handle_syserr
)
# Mark as not destroyed
libev
.
ev_set_userdata
(
self
.
_ptr
,
self
.
_ptr
)
libev
.
ev_prepare_start
(
self
.
_ptr
,
&
self
.
_prepare
)
libev
.
ev_prepare_start
(
self
.
_ptr
,
&
self
.
_prepare
)
libev
.
ev_unref
(
self
.
_ptr
)
libev
.
ev_unref
(
self
.
_ptr
)
...
@@ -489,36 +487,35 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
...
@@ -489,36 +487,35 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
libev
.
ev_timer_stop
(
ptr
,
&
self
.
_periodic_signal_checker
)
libev
.
ev_timer_stop
(
ptr
,
&
self
.
_periodic_signal_checker
)
def
destroy
(
self
):
def
destroy
(
self
):
global
_default_loop_destroyed
cdef
libev
.
ev_loop
*
ptr
=
self
.
_ptr
cdef
libev
.
ev_loop
*
ptr
=
self
.
_ptr
self
.
_ptr
=
NULL
self
.
_ptr
=
NULL
if
ptr
:
if
ptr
:
if
self
.
_default
and
_default_loop_destroyed
:
if
not
libev
.
ev_userdata
(
ptr
)
:
# Whoops! Program error. They destroyed the
default
loop,
# Whoops! Program error. They destroyed the loop,
# using a different loop object. Our _ptr is still
# using a different loop object. Our _ptr is still
# valid, but the libev loop is gone. Doing anything
# valid, but the libev loop is gone. Doing anything
# else with it will likely cause a crash.
# else with it will likely cause a crash.
return
return
# Mark as destroyed
libev
.
ev_set_userdata
(
ptr
,
NULL
)
self
.
_stop_watchers
(
ptr
)
self
.
_stop_watchers
(
ptr
)
if
__SYSERR_CALLBACK
==
self
.
_handle_syserr
:
if
__SYSERR_CALLBACK
==
self
.
_handle_syserr
:
set_syserr_cb
(
None
)
set_syserr_cb
(
None
)
if
self
.
_default
:
_default_loop_destroyed
=
True
libev
.
ev_loop_destroy
(
ptr
)
libev
.
ev_loop_destroy
(
ptr
)
def
__dealloc__
(
self
):
def
__dealloc__
(
self
):
cdef
libev
.
ev_loop
*
ptr
=
self
.
_ptr
cdef
libev
.
ev_loop
*
ptr
=
self
.
_ptr
self
.
_ptr
=
NULL
self
.
_ptr
=
NULL
if
ptr
!=
NULL
:
if
ptr
!=
NULL
:
if
self
.
_default
and
_default_loop_destroyed
:
if
not
libev
.
ev_userdata
(
ptr
)
:
# See destroy(). This is a bug in the caller.
# See destroy(). This is a bug in the caller.
return
return
self
.
_stop_watchers
(
ptr
)
self
.
_stop_watchers
(
ptr
)
if
not
self
.
_default
:
if
not
self
.
_default
:
libev
.
ev_loop_destroy
(
ptr
)
libev
.
ev_loop_destroy
(
ptr
)
# Mark as destroyed
libev
.
ev_set_userdata
(
ptr
,
NULL
)
@
property
@
property
def
ptr
(
self
):
def
ptr
(
self
):
...
...
src/gevent/libev/corecffi.py
View file @
af8e9dac
...
@@ -223,9 +223,6 @@ class loop(AbstractLoop):
...
@@ -223,9 +223,6 @@ class loop(AbstractLoop):
c_flags
|=
libev
.
EVFLAG_FORKCHECK
c_flags
|=
libev
.
EVFLAG_FORKCHECK
if
default
is
None
:
if
default
is
None
:
default
=
True
default
=
True
if
loop
.
_default_loop_destroyed
:
default
=
False
if
default
:
if
default
:
ptr
=
libev
.
gevent_ev_default_loop
(
c_flags
)
ptr
=
libev
.
gevent_ev_default_loop
(
c_flags
)
if
not
ptr
:
if
not
ptr
:
...
@@ -237,6 +234,8 @@ class loop(AbstractLoop):
...
@@ -237,6 +234,8 @@ class loop(AbstractLoop):
if
default
or
globals
()[
"__SYSERR_CALLBACK"
]
is
None
:
if
default
or
globals
()[
"__SYSERR_CALLBACK"
]
is
None
:
set_syserr_cb
(
self
.
_handle_syserr
)
set_syserr_cb
(
self
.
_handle_syserr
)
# Mark this loop as being used.
libev
.
ev_set_userdata
(
ptr
,
ptr
)
return
ptr
return
ptr
def
_init_and_start_check
(
self
):
def
_init_and_start_check
(
self
):
...
@@ -282,6 +281,14 @@ class loop(AbstractLoop):
...
@@ -282,6 +281,14 @@ class loop(AbstractLoop):
if
should_destroy_loop
:
if
should_destroy_loop
:
libev
.
ev_loop_destroy
(
ptr
)
libev
.
ev_loop_destroy
(
ptr
)
def
_can_destroy_loop
(
self
,
ptr
):
# Is it marked as destroyed?
return
libev
.
ev_userdata
(
ptr
)
def
_destroyed_loop
(
self
,
ptr
):
# Mark as destroyed.
libev
.
ev_set_userdata
(
ptr
,
ffi
.
NULL
)
@
property
@
property
def
MAXPRI
(
self
):
def
MAXPRI
(
self
):
return
libev
.
EV_MAXPRI
return
libev
.
EV_MAXPRI
...
...
src/gevent/libev/libev.pxd
View file @
af8e9dac
...
@@ -202,6 +202,8 @@ cdef extern from "libev.h" nogil:
...
@@ -202,6 +202,8 @@ cdef extern from "libev.h" nogil:
ev_loop
*
ev_default_loop
(
unsigned
int
flags
)
ev_loop
*
ev_default_loop
(
unsigned
int
flags
)
ev_loop
*
ev_loop_new
(
unsigned
int
flags
)
ev_loop
*
ev_loop_new
(
unsigned
int
flags
)
void
*
ev_userdata
(
ev_loop
*
)
void
ev_set_userdata
(
ev_loop
*
,
void
*
)
void
ev_loop_destroy
(
ev_loop
*
)
void
ev_loop_destroy
(
ev_loop
*
)
void
ev_loop_fork
(
ev_loop
*
)
void
ev_loop_fork
(
ev_loop
*
)
int
ev_is_default_loop
(
ev_loop
*
)
int
ev_is_default_loop
(
ev_loop
*
)
...
...
src/gevent/libuv/loop.py
View file @
af8e9dac
...
@@ -68,8 +68,6 @@ class loop(AbstractLoop):
...
@@ -68,8 +68,6 @@ class loop(AbstractLoop):
# know this in general on libev
# know this in general on libev
min_sleep_time
=
0.001
# 1ms
min_sleep_time
=
0.001
# 1ms
DEFAULT_LOOP_REGENERATES
=
True
error_handler
=
None
error_handler
=
None
_CHECK_POINTER
=
'uv_check_t *'
_CHECK_POINTER
=
'uv_check_t *'
...
@@ -296,14 +294,16 @@ class loop(AbstractLoop):
...
@@ -296,14 +294,16 @@ class loop(AbstractLoop):
closed_failed
=
libuv
.
uv_loop_close
(
ptr
)
closed_failed
=
libuv
.
uv_loop_close
(
ptr
)
assert
closed_failed
==
0
,
closed_failed
assert
closed_failed
==
0
,
closed_failed
def
_can_destroy_
default_loop
(
self
):
def
_can_destroy_
loop
(
self
,
ptr
):
# We're being asked to destroy a loop that's,
# We're being asked to destroy a loop that's,
# at the time it was constructed, was the default loop.
# at the time it was constructed, was the default loop.
# If loop objects were constructed more than once,
# If loop objects were constructed more than once,
# it may have already been destroyed, though.
# it may have already been destroyed, though.
# We track this in the data member.
# We track this in the data member.
return
self
.
_
ptr
.
data
return
ptr
.
data
def
_destroyed_loop
(
self
,
ptr
):
ptr
.
data
=
ffi
.
NULL
def
debug
(
self
):
def
debug
(
self
):
"""
"""
...
...
src/greentest/test__core.py
View file @
af8e9dac
...
@@ -19,6 +19,9 @@ class TestCore(unittest.TestCase):
...
@@ -19,6 +19,9 @@ class TestCore(unittest.TestCase):
class
TestWatchers
(
unittest
.
TestCase
):
class
TestWatchers
(
unittest
.
TestCase
):
def
makeOne
(
self
):
return
core
.
loop
()
def
test_io
(
self
):
def
test_io
(
self
):
if
sys
.
platform
==
'win32'
:
if
sys
.
platform
==
'win32'
:
# libev raises IOError, libuv raises ValueError
# libev raises IOError, libuv raises ValueError
...
@@ -28,17 +31,17 @@ class TestWatchers(unittest.TestCase):
...
@@ -28,17 +31,17 @@ class TestWatchers(unittest.TestCase):
Error
=
ValueError
Error
=
ValueError
win32
=
False
win32
=
False
with
self
.
assertRaises
(
Error
):
with
self
.
assertRaises
(
Error
):
core
.
loop
().
io
(
-
1
,
1
)
self
.
makeOne
().
io
(
-
1
,
1
)
if
hasattr
(
core
,
'TIMER'
):
if
hasattr
(
core
,
'TIMER'
):
# libev
# libev
with
self
.
assertRaises
(
ValueError
):
with
self
.
assertRaises
(
ValueError
):
core
.
loop
().
io
(
1
,
core
.
TIMER
)
self
.
makeOne
().
io
(
1
,
core
.
TIMER
)
# Test we can set events and io before it's started
# Test we can set events and io before it's started
if
not
win32
:
if
not
win32
:
# We can't do this with arbitrary FDs on windows;
# We can't do this with arbitrary FDs on windows;
# see libev_vfd.h
# see libev_vfd.h
io
=
core
.
loop
().
io
(
1
,
core
.
READ
)
io
=
self
.
makeOne
().
io
(
1
,
core
.
READ
)
io
.
fd
=
2
io
.
fd
=
2
self
.
assertEqual
(
io
.
fd
,
2
)
self
.
assertEqual
(
io
.
fd
,
2
)
io
.
events
=
core
.
WRITE
io
.
events
=
core
.
WRITE
...
@@ -47,15 +50,29 @@ class TestWatchers(unittest.TestCase):
...
@@ -47,15 +50,29 @@ class TestWatchers(unittest.TestCase):
self
.
assertEqual
(
core
.
_events_to_str
(
io
.
events
),
'WRITE|_IOFDSET'
)
self
.
assertEqual
(
core
.
_events_to_str
(
io
.
events
),
'WRITE|_IOFDSET'
)
else
:
else
:
self
.
assertEqual
(
core
.
_events_to_str
(
io
.
events
),
'WRITE'
)
self
.
assertEqual
(
core
.
_events_to_str
(
io
.
events
),
'WRITE'
)
io
.
start
(
lambda
:
None
)
io
.
close
()
io
.
close
()
def
test_timer_constructor
(
self
):
def
test_timer_constructor
(
self
):
with
self
.
assertRaises
(
ValueError
):
with
self
.
assertRaises
(
ValueError
):
core
.
loop
().
timer
(
1
,
-
1
)
self
.
makeOne
().
timer
(
1
,
-
1
)
def
test_signal_constructor
(
self
):
def
test_signal_constructor
(
self
):
with
self
.
assertRaises
(
ValueError
):
with
self
.
assertRaises
(
ValueError
):
core
.
loop
().
signal
(
1000
)
self
.
makeOne
().
signal
(
1000
)
class
TestWatchersDefault
(
TestWatchers
):
def
makeOne
(
self
):
return
core
.
loop
(
default
=
True
)
class
TestWatchersDefaultDestroyed
(
TestWatchers
):
def
makeOne
(
self
):
l
=
core
.
loop
(
default
=
True
)
l
.
destroy
()
del
l
return
core
.
loop
(
default
=
True
)
@
skipOnLibuv
(
"Tests for libev-only functions"
)
@
skipOnLibuv
(
"Tests for libev-only functions"
)
class
TestLibev
(
unittest
.
TestCase
):
class
TestLibev
(
unittest
.
TestCase
):
...
...
src/greentest/test__destroy.py
View file @
af8e9dac
...
@@ -40,12 +40,9 @@ class TestDestroyHub(unittest.TestCase):
...
@@ -40,12 +40,9 @@ class TestDestroyHub(unittest.TestCase):
self
.
assertIsNot
(
hub
.
loop
.
ptr
,
initloop
.
ptr
)
self
.
assertIsNot
(
hub
.
loop
.
ptr
,
initloop
.
ptr
)
self
.
assertNotEqual
(
hub
.
loop
.
ptr
,
initloop
.
ptr
)
self
.
assertNotEqual
(
hub
.
loop
.
ptr
,
initloop
.
ptr
)
# Destroy hub including default loop
, create new hub with non-default loop
.
# Destroy hub including default loop
. The default loop regenerates
.
hub
.
destroy
(
destroy_loop
=
True
)
hub
.
destroy
(
destroy_loop
=
True
)
hub
=
gevent
.
get_hub
()
hub
=
gevent
.
get_hub
()
if
not
getattr
(
hub
.
loop
,
'DEFAULT_LOOP_REGENERATES'
,
False
):
self
.
assertFalse
(
hub
.
loop
.
default
)
else
:
self
.
assertTrue
(
hub
.
loop
.
default
)
self
.
assertTrue
(
hub
.
loop
.
default
)
hub
.
destroy
()
hub
.
destroy
()
...
...
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