Skip to content

Commit 0a63ea7

Browse files
committed
handle recursive calls to gtk_main correctly, and always call uv_dispatch if the Workqueue is not empty
1 parent d26689a commit 0a63ea7

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

src/GLib/signals.jl

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -196,40 +196,45 @@ else
196196
end
197197
function uv_prepare(src::Ptr{Void},timeout::Ptr{Cint})
198198
global expiration, uv_pollfd
199-
local tmout_ms::Cint, tmout_min::Cint = (uv_pollfd::_GPollFD).fd == -1 ? 100 : 5000
199+
local tmout_ms::Cint
200200
evt = Base.eventloop()
201-
if ccall(:uv_loop_alive,Cint,(Ptr{Void},),evt) == 0
202-
tmout_ms = tmout_min
203-
elseif uv_pollfd.revents != 0
201+
if !isempty_workqueue()
204202
tmout_ms = 0
205-
elseif !isempty_workqueue()
203+
elseif ccall(:uv_loop_alive,Cint,(Ptr{Void},),evt) == 0
204+
tmout_ms = -1
205+
elseif uv_pollfd.revents != 0
206206
tmout_ms = 0
207+
elseif @windows ? (VERSION < v"0.3-") : false # uv_backend_timeout broken on windows before Julia v0.3-rc2
208+
tmout_ms = 10
207209
else
208210
tmout_ms = ccall(:uv_backend_timeout,Cint,(Ptr{Void},),evt)
211+
tmout_min::Cint = (uv_pollfd::_GPollFD).fd == -1 ? 100 : 5000
209212
if tmout_ms < 0 || tmout_ms > tmout_min
210213
tmout_ms = tmout_min
211214
end
212215
end
213216
timeout != C_NULL && unsafe_store!(timeout, tmout_ms)
214-
if tmout_ms > 0
217+
if tmout_ms < 0
218+
expiration = typemax(Uint64)
219+
elseif tmout_ms > 0
215220
now = ccall((:g_source_get_time,GLib.libglib),Uint64,(Ptr{Void},),src)
216221
expiration = convert(Uint64,now + tmout_ms*1000)
217-
else
222+
else #tmout_ms == 0
218223
expiration = uint64(0)
219224
end
220225
int32(tmout_ms == 0)
221226
end
222227
function uv_check(src::Ptr{Void})
223228
global expiration
224229
ex = expiration::Uint64
225-
if ccall(:uv_loop_alive,Cint,(Ptr{Void},),Base.eventloop()) == 0
230+
if !isempty_workqueue()
231+
return int32(1)
232+
elseif ccall(:uv_loop_alive,Cint,(Ptr{Void},),Base.eventloop()) == 0
226233
return int32(0)
227234
elseif ex == 0
228235
return int32(1)
229236
elseif uv_pollfd.revents != 0
230237
return int32(1)
231-
elseif !isempty_workqueue()
232-
return int32(1)
233238
else
234239
now = ccall((:g_source_get_time,GLib.libglib),Uint64,(Ptr{Void},),src)
235240
return int32(ex <= now)
@@ -240,10 +245,33 @@ function uv_dispatch{T}(src::Ptr{Void},callback::Ptr{Void},data::T)
240245
ret
241246
end
242247

248+
yield_stack = Task[] # need to make sure we return to g_loop_run_run in the same order we were called
249+
if VERSION < v"0.3-"
250+
function schedule_and_wait(task::Task)
251+
task.runnable || schedule(task)
252+
wait()
253+
end
254+
else
255+
function schedule_and_wait(task::Task)
256+
# unfair scheduler version of Base.schedule_and_wait
257+
if task.state == :runnable
258+
yieldto(task)
259+
else
260+
wait()
261+
end
262+
end
263+
end
243264
function g_yield(data)
265+
global yield_stack
266+
ct = current_task()
267+
push!(yield_stack, ct)
244268
g_siginterruptible() do
245269
yield()
246270
end
271+
newtask = pop!(yield_stack)
272+
if newtask != ct
273+
schedule_and_wait(newtask)
274+
end
247275
int32(true)
248276
end
249277

src/events.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function gtk_main()
55
end
66

77
function gtk_quit()
8-
ccall((:gtk_quit,libgtk),Void,())
8+
ccall((:gtk_main_quit,libgtk),Void,())
99
end
1010

1111
function __init__()

0 commit comments

Comments
 (0)