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
Hide 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 @@
extension implementation only) deallocated (garbage collected). See
: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)
==================
...
...
src/gevent/_ffi/loop.py
View file @
af8e9dac
...
...
@@ -487,12 +487,11 @@ class AbstractLoop(object):
"""
if
self
.
_ptr
:
try
:
if
self
.
_default
:
if
not
self
.
_can_destroy_default_loop
():
return
False
type
(
self
).
_default_loop_destroyed
=
True
if
not
self
.
_can_destroy_loop
(
self
.
_ptr
):
return
False
self
.
_destroyed_loop
(
self
.
_ptr
)
self
.
_stop_aux_watchers
()
finally
:
# not ffi.NULL, we don't want something that can be
# passed to C and crash later. This will create nice friendly
...
...
@@ -501,8 +500,11 @@ class AbstractLoop(object):
return
True
def
_can_destroy_default_loop
(
self
):
return
not
type
(
self
).
_default_loop_destroyed
def
_can_destroy_loop
(
self
,
ptr
):
raise
NotImplementedError
()
def
_destroyed_loop
(
self
,
ptr
):
raise
NotImplementedError
()
@
property
def
ptr
(
self
):
...
...
src/gevent/libev/corecext.pyx
View file @
af8e9dac
...
...
@@ -259,8 +259,6 @@ cdef bint _check_loop(loop loop) except -1:
return
1
cdef
bint
_default_loop_destroyed
=
False
cdef
public
class
callback
[
object
PyGeventCallbackObject
,
type
PyGeventCallback_Type
]:
cdef
public
object
callback
...
...
@@ -419,8 +417,6 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
c_flags
|=
libev
.
EVFLAG_FORKCHECK
if
default
is
None
:
default
=
True
if
_default_loop_destroyed
:
default
=
False
if
default
:
self
.
_default
=
1
self
.
_ptr
=
libev
.
gevent_ev_default_loop
(
c_flags
)
...
...
@@ -436,6 +432,8 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
if
default
or
__SYSERR_CALLBACK
is
None
:
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_unref
(
self
.
_ptr
)
...
...
@@ -489,36 +487,35 @@ cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]:
libev
.
ev_timer_stop
(
ptr
,
&
self
.
_periodic_signal_checker
)
def
destroy
(
self
):
global
_default_loop_destroyed
cdef
libev
.
ev_loop
*
ptr
=
self
.
_ptr
self
.
_ptr
=
NULL
if
ptr
:
if
self
.
_default
and
_default_loop_destroyed
:
# Whoops! Program error. They destroyed the
default
loop,
if
not
libev
.
ev_userdata
(
ptr
)
:
# Whoops! Program error. They destroyed the loop,
# using a different loop object. Our _ptr is still
# valid, but the libev loop is gone. Doing anything
# else with it will likely cause a crash.
return
# Mark as destroyed
libev
.
ev_set_userdata
(
ptr
,
NULL
)
self
.
_stop_watchers
(
ptr
)
if
__SYSERR_CALLBACK
==
self
.
_handle_syserr
:
set_syserr_cb
(
None
)
if
self
.
_default
:
_default_loop_destroyed
=
True
libev
.
ev_loop_destroy
(
ptr
)
def
__dealloc__
(
self
):
cdef
libev
.
ev_loop
*
ptr
=
self
.
_ptr
self
.
_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.
return
self
.
_stop_watchers
(
ptr
)
if
not
self
.
_default
:
libev
.
ev_loop_destroy
(
ptr
)
# Mark as destroyed
libev
.
ev_set_userdata
(
ptr
,
NULL
)
@
property
def
ptr
(
self
):
...
...
src/gevent/libev/corecffi.py
View file @
af8e9dac
...
...
@@ -223,9 +223,6 @@ class loop(AbstractLoop):
c_flags
|=
libev
.
EVFLAG_FORKCHECK
if
default
is
None
:
default
=
True
if
loop
.
_default_loop_destroyed
:
default
=
False
if
default
:
ptr
=
libev
.
gevent_ev_default_loop
(
c_flags
)
if
not
ptr
:
...
...
@@ -237,6 +234,8 @@ class loop(AbstractLoop):
if
default
or
globals
()[
"__SYSERR_CALLBACK"
]
is
None
:
set_syserr_cb
(
self
.
_handle_syserr
)
# Mark this loop as being used.
libev
.
ev_set_userdata
(
ptr
,
ptr
)
return
ptr
def
_init_and_start_check
(
self
):
...
...
@@ -282,6 +281,14 @@ class loop(AbstractLoop):
if
should_destroy_loop
:
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
def
MAXPRI
(
self
):
return
libev
.
EV_MAXPRI
...
...
src/gevent/libev/libev.pxd
View file @
af8e9dac
...
...
@@ -202,6 +202,8 @@ cdef extern from "libev.h" nogil:
ev_loop
*
ev_default_loop
(
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_fork
(
ev_loop
*
)
int
ev_is_default_loop
(
ev_loop
*
)
...
...
src/gevent/libuv/loop.py
View file @
af8e9dac
...
...
@@ -68,8 +68,6 @@ class loop(AbstractLoop):
# know this in general on libev
min_sleep_time
=
0.001
# 1ms
DEFAULT_LOOP_REGENERATES
=
True
error_handler
=
None
_CHECK_POINTER
=
'uv_check_t *'
...
...
@@ -296,14 +294,16 @@ class loop(AbstractLoop):
closed_failed
=
libuv
.
uv_loop_close
(
ptr
)
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,
# at the time it was constructed, was the default loop.
# If loop objects were constructed more than once,
# it may have already been destroyed, though.
# 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
):
"""
...
...
src/greentest/test__core.py
View file @
af8e9dac
...
...
@@ -19,6 +19,9 @@ class TestCore(unittest.TestCase):
class
TestWatchers
(
unittest
.
TestCase
):
def
makeOne
(
self
):
return
core
.
loop
()
def
test_io
(
self
):
if
sys
.
platform
==
'win32'
:
# libev raises IOError, libuv raises ValueError
...
...
@@ -28,17 +31,17 @@ class TestWatchers(unittest.TestCase):
Error
=
ValueError
win32
=
False
with
self
.
assertRaises
(
Error
):
core
.
loop
().
io
(
-
1
,
1
)
self
.
makeOne
().
io
(
-
1
,
1
)
if
hasattr
(
core
,
'TIMER'
):
# libev
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
if
not
win32
:
# We can't do this with arbitrary FDs on windows;
# see libev_vfd.h
io
=
core
.
loop
().
io
(
1
,
core
.
READ
)
io
=
self
.
makeOne
().
io
(
1
,
core
.
READ
)
io
.
fd
=
2
self
.
assertEqual
(
io
.
fd
,
2
)
io
.
events
=
core
.
WRITE
...
...
@@ -47,15 +50,29 @@ class TestWatchers(unittest.TestCase):
self
.
assertEqual
(
core
.
_events_to_str
(
io
.
events
),
'WRITE|_IOFDSET'
)
else
:
self
.
assertEqual
(
core
.
_events_to_str
(
io
.
events
),
'WRITE'
)
io
.
start
(
lambda
:
None
)
io
.
close
()
def
test_timer_constructor
(
self
):
with
self
.
assertRaises
(
ValueError
):
core
.
loop
().
timer
(
1
,
-
1
)
self
.
makeOne
().
timer
(
1
,
-
1
)
def
test_signal_constructor
(
self
):
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"
)
class
TestLibev
(
unittest
.
TestCase
):
...
...
src/greentest/test__destroy.py
View file @
af8e9dac
...
...
@@ -40,13 +40,10 @@ class TestDestroyHub(unittest.TestCase):
self
.
assertIsNot
(
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
=
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
()
...
...
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