Skip to content

Commit be0c830

Browse files
committed
protect GIL with Julia reentrant mutex
1 parent 2cd566a commit be0c830

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

‎Project.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "PythonCall"
22
uuid = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
33
authors = ["Christopher Doris <github.com/cjdoris>"]
4-
version = "0.9.35"
4+
version = "0.9.36"
55

66
[deps]
77
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"

‎src/GIL/GIL.jl‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ if Base.VERSION ≥ v"1.11"
2525
)
2626
end
2727

28+
const LOCK = ReentrantLock()
29+
30+
function __init__()
31+
Base.lock(LOCK)
32+
return nothing
33+
end
2834

2935
"""
3036
lock(f)
@@ -42,11 +48,16 @@ See [`@lock`](@ref) for the macro form.
4248
This function is experimental. Its semantics may be changed without notice.
4349
"""
4450
function lock(f)
51+
Base.lock(LOCK)
52+
task = current_task()
53+
sticky, task.sticky = task.sticky, true
4554
state = C.PyGILState_Ensure()
4655
try
4756
f()
4857
finally
4958
C.PyGILState_Release(state)
59+
task.sticky = sticky
60+
Base.unlock(LOCK)
5061
end
5162
end
5263

@@ -67,11 +78,16 @@ The macro equivalent of [`lock`](@ref).
6778
"""
6879
macro lock(expr)
6980
quote
81+
Base.lock($LOCK)
82+
task = current_task()
83+
sticky, task.sticky = task.sticky, true
7084
state = C.PyGILState_Ensure()
7185
try
7286
$(esc(expr))
7387
finally
7488
C.PyGILState_Release(state)
89+
task.sticky = sticky
90+
Base.unlock($LOCK)
7591
end
7692
end
7793
end
@@ -92,11 +108,17 @@ See [`@unlock`](@ref) for the macro form.
92108
This function is experimental. Its semantics may be changed without notice.
93109
"""
94110
function unlock(f)
111+
if !islocked(LOCK)
112+
error("GIL is not held")
113+
end
114+
115+
Base.unlock(LOCK)
95116
state = C.PyEval_SaveThread()
96117
try
97118
f()
98119
finally
99120
C.PyEval_RestoreThread(state)
121+
Base.lock(LOCK)
100122
end
101123
end
102124

@@ -117,11 +139,17 @@ The macro equivalent of [`unlock`](@ref).
117139
"""
118140
macro unlock(expr)
119141
quote
142+
if !islocked($LOCK)
143+
error("GIL is not held")
144+
end
145+
146+
Base.unlock($LOCK)
120147
state = C.PyEval_SaveThread()
121148
try
122149
$(esc(expr))
123150
finally
124151
C.PyEval_RestoreThread(state)
152+
Base.lock($LOCK)
125153
end
126154
end
127155
end

0 commit comments

Comments
 (0)