-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pep 554 : High level implementation of sub-interpreters module #1
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good start. Missing pieces:
Interpreter
class- channels
- unit tests (I saw only functional tests)
For the tests I left a number of suggestions, but only do what makes sense. I just wanted to present one approach (which I find effective).
|
||
This module constructs higher-level interpreters interfaces on top of the lower | ||
level :mod:`_interpreters` module. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would probably make sense to add a glossary entry for "subinterpreter" and to link to it above.
Likewise there should be a brief mention of the "main" interpreter and maybe a link for it (either a new glossary entry or the section in the C-API docs).
Doc/library/interpreters.rst
Outdated
@@ -0,0 +1,44 @@ | |||
:mod:`interpreters` --- High-level Sub-interpreters Module |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's be sure to be consistent about naming. FWIW, at this point I'm a fan of "subinterpreter" rather than "sub-interpreter", but it's not crucial to me. :) The most important point is that we be consistent.
main = interpreters.get_main() | ||
cur = interpreters.get_current() | ||
self.assertEqual(cur, main) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to add a function test where get_current()
is called in a subinterpreter.
def test_create(self): | ||
id = interpreters.create() | ||
self.assertIn(id, interpreters.list_all()) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to add a function test that creates more than one. You could do that in the existing test.
Co-Authored-By: Eric Snow <[email protected]>
Co-Authored-By: Eric Snow <[email protected]>
Co-Authored-By: Eric Snow <[email protected]>
Co-Authored-By: Eric Snow <[email protected]>
Co-Authored-By: Eric Snow <[email protected]>
Co-Authored-By: Eric Snow <[email protected]>
Co-Authored-By: Eric Snow <[email protected]>
Lib/interpreters.py
Outdated
No longer associate the current interpreterwith the channel | ||
(on the sending end). | ||
""" | ||
return _interpreters.(self.id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this say return _interpreters.channel_release(self.id)
? Currently a syntax error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Am working on it.
Lib/interpreters.py
Outdated
"""Subinterpreters High Level Module.""" | ||
|
||
import _interpreters | ||
import logger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be import logging
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is my first pass, but I'll re-review this shortly again.
Doc/library/interpreters.rst
Outdated
.. method:: destroy() | ||
|
||
Destroy the identified interpreter. Attempting to destroy the current | ||
interpreter results in a RuntimeError. So does an unrecognized ID. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think current is not a good wording here, what do you mean by current. From PEP-554 the idea was to not be able destroy a running interpreter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last sentence is also not clear, what ID, how is it unrecognised?
Lib/interpreters.py
Outdated
obj = _interpreters.channel_recv(self.id) | ||
if obj == None: | ||
wait(timeout) | ||
obj = obj = _interpreters.channel_recv(self.id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
obj = obj = _interpreters.channel_recv(self.id) | |
obj = _interpreters.channel_recv(self.id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
channel_recv
doesn't return None
when channel is empty, but rather it raises ChannelEmptyError
. So I'd imagine this method try to read the channel, catch the error, and re-try. There are several possible approaches for this:
- it can be either poll (but channels don't support that, as of now),
- we could divide the input timeout by some "magical" number and re-try every X amount of time.
Lib/interpreters.py
Outdated
|
||
Like recv(), but return the default instead of waiting. | ||
""" | ||
return _interpreters.channel_recv(self.id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return _interpreters.channel_recv(self.id) | |
try: | |
return _interpreters.channel_recv(self.id) | |
except _interpreters.ChannelEmptyError: | |
return default |
@@ -293,7 +293,7 @@ channel_exceptions_init(PyObject *ns) | |||
// XXX Move the exceptions into per-module memory? | |||
|
|||
// A channel-related operation failed. | |||
ChannelError = PyErr_NewException("_xxsubinterpreters.ChannelError", | |||
ChannelError = PyErr_NewException("_interpreters.ChannelError", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think with this we should also consider renaming the file, for consistency.
``` Direct leak of 8 byte(s) in 1 object(s) allocated from: #0 0x7f008bf19667 in __interceptor_malloc (/lib64/libasan.so.6+0xb0667) #1 0x7f007a0bee4a in subprocess_fork_exec /home/heimes/dev/python/cpython/Modules/_posixsubprocess.c:774 python#2 0xe0305b in cfunction_call Objects/methodobject.c:546 ``` Signed-off-by: Christian Heimes <[email protected]>
1: Initial CI support. r=ltratt a=vext01 This is preliminary CI support for CPython. A test is failing: ``` test test_signal failed -- Traceback (most recent call last): File "/ci/Lib/test/test_signal.py", line 184, in test_main self.fail(tb) AssertionError: Traceback (most recent call last): File "/ci/Lib/test/test_signal.py", line 167, in test_main self.run_test() File "/ci/Lib/test/test_signal.py", line 94, in run_test child = ignoring_eintr(subprocess.Popen, ['kill', '-HUP', str(pid)]) File "/ci/Lib/test/test_signal.py", line 32, in ignoring_eintr return __func(*args, **kwargs) File "/ci/Lib/subprocess.py", line 394, in __init__ errread, errwrite) File "/ci/Lib/subprocess.py", line 1047, in _execute_child raise child_exception OSError: [Errno 2] No such file or directory ``` Does anyone know anything about it? Could have cloned at a bad time? Co-authored-by: Edd Barrett <[email protected]>
) Fix test_gdb.test_pycfunction() for Python built with clang -Og. Tolerate inlined functions in the gdb traceback. When _testcapimodule.c is built by clang -Og, _null_to_none() is inlined in meth_varargs() and so gdb returns _null_to_none() as the frame #1. If it's not inlined, meth_varargs() is the frame #1.
…python#91466) Fix an uninitialized bool in exception print context. `struct exception_print_context.need_close` was uninitialized. Found by oss-fuzz in a test case running under the undefined behavior sanitizer. https://oss-fuzz.com/testcase-detail/6217746058182656 ``` Python/pythonrun.c:1241:28: runtime error: load of value 253, which is not a valid value for type 'bool' #0 0xbf2203 in print_chained cpython3/Python/pythonrun.c:1241:28 #1 0xbea4bb in print_exception_cause_and_context cpython3/Python/pythonrun.c:1320:19 python#2 0xbea4bb in print_exception_recursive cpython3/Python/pythonrun.c:1470:13 python#3 0xbe9e39 in _PyErr_Display cpython3/Python/pythonrun.c:1517:9 ``` Pretty obvious what the ommission was upon code inspection.
Sub-Interpreters in Standard Library.
Initial implementation of the High level sub-interpreters module.