On Mon, Jun 6, 2016 at 6:29 AM, Ulf Worsoe <[email protected]> wrote:
> The symbol jl_signal_pending is exported, and the following appears to work
> (assuming, of course, sig_atomic_t is an int):
>
> 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
This should be "safe" (other than that running a julia function on an
unmanaged thread is almost never safe)
It won't work on 0.5 though.
>
>
> 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)())
> {
> while (1)
> {
> sleep(1);
> if (callback())
> return;
> }
> }
>
> If this a safe way to check for ctrl-c?
>
>
> 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 <[email protected]> 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?