Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Doc/c-api/init.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1834,6 +1834,10 @@ pointer and a void pointer argument.
called from the main interpreter. Each subinterpreter now has its own
list of scheduled calls.

.. versionchanged:: 3.12
This function now always schedules *func* to be run in the main
interpreter.

.. _profiling:

Profiling and Tracing
Expand Down
11 changes: 11 additions & 0 deletions Doc/library/os.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo

- :data:`RWF_HIPRI`
- :data:`RWF_NOWAIT`
- :data:`RWF_DONTCACHE`

Return the total number of bytes actually read which can be less than the
total capacity of all the objects.
Expand Down Expand Up @@ -1546,6 +1547,15 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo
.. versionadded:: 3.7


.. data:: RWF_DONTCACHE

Use uncached buffered IO.

.. availability:: Linux >= 6.14

.. versionadded:: next


.. function:: ptsname(fd, /)

Return the name of the slave pseudo-terminal device associated with the
Expand Down Expand Up @@ -1587,6 +1597,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo
- :data:`RWF_DSYNC`
- :data:`RWF_SYNC`
- :data:`RWF_APPEND`
- :data:`RWF_DONTCACHE`

Return the total number of bytes actually written.

Expand Down
2 changes: 1 addition & 1 deletion Doc/library/zoneinfo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ Functions

This function only includes canonical zone names and does not include
"special" zones such as those under the ``posix/`` and ``right/``
directories, or the ``posixrules`` zone.
directories, the ``posixrules`` or the ``localtime`` zone.

.. caution::

Expand Down
11 changes: 9 additions & 2 deletions Doc/using/android.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,15 @@ If you're sure you want to do all of this manually, read on. You can use the
:source:`testbed app <Android/testbed>` as a guide; each step below contains a
link to the relevant file.

* Build Python by following the instructions in :source:`Android/README.md`.
This will create the directory ``cross-build/HOST/prefix``.
* First, acquire a build of Python for Android:

* The easiest way is to download an Android release from `python.org
<https://www.python.org/downloads/android/>`__. The ``prefix`` directory
mentioned below is at the top level of the package.

* Or if you want to build it yourself, follow the instructions in
:source:`Android/README.md`. The ``prefix`` directory will be created under
:samp:`cross-build/{HOST}`.

* Add code to your :source:`build.gradle <Android/testbed/app/build.gradle.kts>`
file to copy the following items into your project. All except your own Python
Expand Down
1 change: 1 addition & 0 deletions Include/cpython/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ struct _ts {
# define _PyThreadState_WHENCE_THREADING 3
# define _PyThreadState_WHENCE_GILSTATE 4
# define _PyThreadState_WHENCE_EXEC 5
# define _PyThreadState_WHENCE_THREADING_DAEMON 6
#endif

/* Currently holds the GIL. Must be its own field to avoid data races */
Expand Down
56 changes: 56 additions & 0 deletions Lib/test/test_atexit.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,62 @@ def thready():
# want them to affect the rest of the tests.
script_helper.assert_python_ok("-c", textwrap.dedent(source))

@threading_helper.requires_working_threading()
def test_thread_created_in_atexit(self):
source = """if True:
import atexit
import threading
import time


def run():
print(24)
time.sleep(1)
print(42)

@atexit.register
def start_thread():
threading.Thread(target=run).start()
"""
return_code, stdout, stderr = script_helper.assert_python_ok("-c", source)
self.assertEqual(return_code, 0)
self.assertEqual(stdout, f"24{os.linesep}42{os.linesep}".encode("utf-8"))
self.assertEqual(stderr, b"")

@threading_helper.requires_working_threading()
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
def test_thread_created_in_atexit_subinterpreter(self):
try:
from concurrent import interpreters
except ImportError:
self.skipTest("subinterpreters are not available")

read, write = os.pipe()
source = f"""if True:
import atexit
import threading
import time
import os

def run():
os.write({write}, b'spanish')
time.sleep(1)
os.write({write}, b'inquisition')

@atexit.register
def start_thread():
threading.Thread(target=run).start()
"""
interp = interpreters.create()
try:
interp.exec(source)

# Close the interpreter to invoke atexit callbacks
interp.close()
self.assertEqual(os.read(read, 100), b"spanishinquisition")
finally:
os.close(read)
os.close(write)

@support.cpython_only
class SubinterpreterTest(unittest.TestCase):
Expand Down
66 changes: 66 additions & 0 deletions Lib/test/test_capi/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from test import support
from test.support import MISSING_C_DOCSTRINGS
from test.support import import_helper
from test.support import script_helper
from test.support import threading_helper
from test.support import warnings_helper
from test.support import requires_limited_api
Expand Down Expand Up @@ -1641,6 +1642,36 @@ def subthread():

self.assertEqual(actual, int(interpid))

@threading_helper.requires_working_threading()
def test_pending_call_creates_thread(self):
source = """
import _testinternalcapi
import threading
import time


def output():
print(24)
time.sleep(1)
print(42)


def callback():
threading.Thread(target=output).start()


def create_pending_call():
time.sleep(1)
_testinternalcapi.simple_pending_call(callback)


threading.Thread(target=create_pending_call).start()
"""
return_code, stdout, stderr = script_helper.assert_python_ok('-c', textwrap.dedent(source))
self.assertEqual(return_code, 0)
self.assertEqual(stdout, f"24{os.linesep}42{os.linesep}".encode("utf-8"))
self.assertEqual(stderr, b"")


class SubinterpreterTest(unittest.TestCase):

Expand Down Expand Up @@ -1949,6 +1980,41 @@ def test_module_state_shared_in_global(self):
subinterp_attr_id = os.read(r, 100)
self.assertEqual(main_attr_id, subinterp_attr_id)

@threading_helper.requires_working_threading()
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
@requires_subinterpreters
def test_pending_call_creates_thread_subinterpreter(self):
interpreters = import_helper.import_module("concurrent.interpreters")
r, w = os.pipe()
source = f"""if True:
import _testinternalcapi
import threading
import time
import os


def output():
time.sleep(1)
os.write({w}, b"x")


def callback():
threading.Thread(target=output).start()


def create_pending_call():
time.sleep(1)
_testinternalcapi.simple_pending_call(callback)


threading.Thread(target=create_pending_call).start()
"""
interp = interpreters.create()
interp.exec(source)
interp.close()
data = os.read(r, 1)
self.assertEqual(data, b"x")


@requires_subinterpreters
class InterpreterConfigTests(unittest.TestCase):
Expand Down
Loading
Loading