Reputation: 57281
I would like to test how my application responds to functions that hold the GIL. Is there a convenient function that holds the GIL for a predictable (or even a significant) amount of time?
My ideal function would be something that operated like time.sleep
except that, unlike sleep, it would hold the GIL
Upvotes: 5
Views: 2109
Reputation: 2491
You can use a C library's sleep function in "PyDLL" mode.
# Use libc in ctypes "PyDLL" mode, which prevents CPython from
# releasing the GIL during procedure calls.
_libc_name = ctypes.util.find_library("c")
if _libc_name is None:
raise RuntimeError("Cannot find libc")
libc_py = ctypes.PyDLL(_libc_name)
...
libc_py.usleep(...)
(See https://gist.github.com/jonashaag/d455671003205120a864d3aa69536661 for details on how to pickle the reference, for example if using in a distributed computing environment.)
Upvotes: 2
Reputation: 29342
A simple, but hacky, way to hold the GIL is to use the re
module with a known-to-be-slow match:
import re
re.match(r'(a?){30}a{30}', 'a'*30)
On my machine, this holds the GIL for 48 seconds with Python 2.7.14 (and takes almost as long on 3.6.3). However, this relies on implementation details, and may stop working if the re
module gets improvements.
A more direct approach would be to write a c module that just sleeps. Python C extensions don't automatically release the GIL (unlike, say, ctypes). Follow the hellomodule example here, and replace the printf()
with a call to sleep()
(or the Windows equivalent). Once you build the module, you'll have a GIL holding function you can use anywhere.
Upvotes: 4