The symbol jl_signal_pending is exported, and the following appears to work:
function callback_func() if unsafe_load(cglobal(:jl_signal_pending, Cint),1) > Cint(0) return convert(Cint,1) else return convert(Cint,0) end end function do_native_call() disable_sigint() do ccall(:my_c_function, Void, (Ptr{Void},), cfunction(callback_func, Cint,())) end end and on the native side: void my_c_func(int (*callback)()) { } On Monday, June 6, 2016 at 10:25:29 AM UTC+2, Ulf Worsoe wrote: > > It appears to work in Julia 0.4 - at least I hasn't crashed yet - but I > have not really stress tested it. > > Just disabling SIGINT only gets me half of the way. It will stop the > function from crashing, but these calls may run for a long time, and in > some cases it may be relevant to manually stop the call when a sufficiently > good solution has been found. Is there any robust way to receive > notification about ctrl-c or check if a ctrl-c has happened before > returning from a native function? > > On Friday, June 3, 2016 at 5:24:28 PM UTC+2, Yichao Yu wrote: >> >> On Fri, Jun 3, 2016 at 4:51 AM, Ulf Worsoe <ulf.w...@mosek.com> wrote: >> > I am developing Mosek.jl. >> > >> > That library works by creating a task object, adding data to it and >> calling >> > a solve function. When a user in interactive mode hits ctrl-c, calls to >> > native functions are terminated, and that leaves the task object in an >> > inconsistent state, meaning that even calling the destructor may cause >> it to >> > segfault. This is why I am trying to take over the ctrl-c signal. I do >> > something like this >> > ( >> https://github.com/JuliaOpt/Mosek.jl/blob/sigint/src/msk8_functions.jl#L2291-L2308): >> >> >> > msk_global_break = false >> > function msk_global_sigint_handler(sig::Int32) >> > println("msk_global_sigint_handler") >> > global msk_global_break = true >> > nothing >> > end >> > >> > function optimize(task_:: MSKtask) >> > trmcode_ = Array(Int32,(1,)) >> > SIGINT=2 >> > old_sighandler = >> > >> ccall((:signal,"libc"),Ptr{Void},(Cint,Ptr{Void}),SIGINT,cfunction(msk_global_sigint_handler, >> >> >> > Void, (Cint,))) >> > res = @msk_ccall( >> > "optimizetrm",Int32,(Ptr{Void},Ptr{Int32}),task_.task,trmcode_) >> > ccall((:signal,"libc"),Void,(Cint,Ptr{Void}),SIGINT,old_sighandler) >> > global msk_global_break >> > if msk_global_break >> > global msk_global_break = false >> > throw(InterruptException()) >> > end >> > >> > if res != MSK_RES_OK >> > msg = getlasterror(task_) >> > throw(MosekError(res,msg)) >> > end >> > (convert(Int32,trmcode_[1])) >> > end >> > >> > During long calls the msk_global_break flag is checked, and if set, the >> > operation terminates in a controlled manner. >> >> This will not work on 0.5 at least, not sure about 0.4. >> SIGINT is blocked on all threads and there are always more then one >> threads, one of them unmanaged and can't run any julia code. >> You should be able to just use `disable_sigint` to do this on both 0.4 >> and 0.5. It is not necessary on 0.5 if the ccall doesn't call back to >> julia. >> >> > >> > I have seen older answers to similar questions, saying that this could >> cause >> > problems, but have been told that threading may be handled different >> now. Is >> > this something I can expect to work in Julia 0.4 and/or 0.5? In >> particular, >> > if the native optimizetrm function creates multiple threads, will this >> still >> > work? >> >