MRocklin
MRocklin

Reputation: 57281

Simple Python function that holds the GIL

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

Answers (2)

Jonas H.
Jonas H.

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

itsadok
itsadok

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

Related Questions