Skip to content
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

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

nanjekyejoannah
Copy link
Owner

Sub-Interpreters in Standard Library.

Initial implementation of the High level sub-interpreters module.

@nanjekyejoannah nanjekyejoannah changed the title Pep 554 Pep 554 : High level implementation of sub-interpreters module Sep 10, 2019
@nanjekyejoannah
Copy link
Owner Author

cc @ericsnowcurrently

Copy link

@ericsnowcurrently ericsnowcurrently left a 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).

Doc/library/interpreters.rst Outdated Show resolved Hide resolved

This module constructs higher-level interpreters interfaces on top of the lower
level :mod:`_interpreters` module.

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).

@@ -0,0 +1,44 @@
:mod:`interpreters` --- High-level Sub-interpreters Module

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.

Doc/library/interpreters.rst Outdated Show resolved Hide resolved
Doc/library/interpreters.rst Show resolved Hide resolved
main = interpreters.get_main()
cur = interpreters.get_current()
self.assertEqual(cur, main)

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.

Lib/test/test_interpreters.py Outdated Show resolved Hide resolved
Lib/test/test_interpreters.py Outdated Show resolved Hide resolved
Lib/test/test_interpreters.py Outdated Show resolved Hide resolved
def test_create(self):
id = interpreters.create()
self.assertIn(id, interpreters.list_all())

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.

No longer associate the current interpreterwith the channel
(on the sending end).
"""
return _interpreters.(self.id)

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.

Copy link
Owner Author

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.

"""Subinterpreters High Level Module."""

import _interpreters
import logger

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?

Copy link

@soltysh soltysh left a 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.

.. method:: destroy()

Destroy the identified interpreter. Attempting to destroy the current
interpreter results in a RuntimeError. So does an unrecognized ID.
Copy link

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.

Copy link

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?

obj = _interpreters.channel_recv(self.id)
if obj == None:
wait(timeout)
obj = obj = _interpreters.channel_recv(self.id)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
obj = obj = _interpreters.channel_recv(self.id)
obj = _interpreters.channel_recv(self.id)

Copy link

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.


Like recv(), but return the default instead of waiting.
"""
return _interpreters.channel_recv(self.id)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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",
Copy link

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.

nanjekyejoannah pushed a commit that referenced this pull request Jul 5, 2020
```
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]>
nanjekyejoannah pushed a commit that referenced this pull request Mar 28, 2022
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]>
JelleZijlstra pushed a commit that referenced this pull request Apr 12, 2022
)

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.
nanjekyejoannah pushed a commit that referenced this pull request Oct 4, 2022
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants