Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

signal handler #233

Open
benlorenz opened this issue Mar 10, 2020 · 9 comments · Fixed by #265
Open

signal handler #233

benlorenz opened this issue Mar 10, 2020 · 9 comments · Fixed by #265
Labels
question Further information is requested

Comments

@benlorenz
Copy link
Member

We set the signal handler for polymake.jl in initialize_polymake but this breaks Ctrl+C in julia afterwards.
Either we remove this or we need to set and unset this around every computation, and make sure we reset it to he correct one.

julia> sleep(5);
^CERROR: InterruptException:
Stacktrace:
 [1] poptaskref(::Base.InvasiveLinkedListSynchronized{Task}) at ./task.jl:564
 [2] wait() at ./task.jl:591
 [3] wait(::Base.GenericCondition{Base.Threads.SpinLock}) at ./condition.jl:104
 [4] stream_wait(::Timer, ::Base.GenericCondition{Base.Threads.SpinLock}) at ./stream.jl:47
 [5] wait(::Timer) at ./asyncevent.jl:116
 [6] sleep(::Int64) at ./asyncevent.jl:188
 [7] top-level scope at REPL[1]:1

julia> using Polymake
polymake version 4.0
Copyright (c) 1997-2020
Ewgenij Gawrilow, Michael Joswig, and the polymake team
Technische Universität Berlin, Germany
https://polymake.org
...

julia> sleep(5);
^C^C^C  (nothing happens)
julia> 

After removing the set_interrupt_signal from the polymake init Ctrl+C aborts julia and returns to the shell:

julia> using Polymake
polymake version 4.0
...

julia> sleep(5)
^C
lorenz $

It seems perl is also messing with the signal handler.

@benlorenz benlorenz added the question Further information is requested label Mar 10, 2020
@benlorenz benlorenz added this to the 0.3.1 milestone Mar 10, 2020
@kalmarek
Copy link
Contributor

ok, so that means that polymake always grabs the interrupt and does nothing with it?
I thought what we set-up was passing the interrupt from julia to polymake if we're in polymake function;

but I can reproduce this; I guess it's best to revert this change and think about a solution to the following scenario:

julia> s = rand_sphere(15, 1000);

julia> s.FACETS;
^C
Interrupted

julia>

i.e. how to break a computation that has no chance of ever finishing without using ^Z + kill ;)

@benlorenz
Copy link
Member Author

polymake can set a signal handler but we can remove/disable that (or use a different signal), but also perl does many calls to sigaction.
I dont think polymake is responsible for the 'kills julia' behaviour.

There can be only one signal handler for a given signal, so we are overwriting the one from julia. And the behaviour of the polymake signal handler depends on the currently running code:

  • It should abort rather quickly when polymake is running perl code.
  • But if polymake is running some C++ code or foreign library code it will not abort until it returns to perl.

The second point is to avoid any inconsistent state, just stopping arbitrary C or C++ code might leave plenty of leaking memory in the best case, invalid pointers in global variables otherwise.
So I don't think you can get a safe way to abort p.FACETS.

Is it possible on the julia side to have custom code triggered when Ctrl+C is pressed, the REPL is probably running in a different thread?
Then we could set polymake to a signal other than SIGINT and send that custom signal via pthread_kill if we know the correct thread?
(But most signal seem already in use by julia: https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c )

@kalmarek
Copy link
Contributor

I just meant that the only possibility of stopping the endless computation is to suspend and then kill julia process; What would be ideal is to pass the interrupt to polymake, which passes the interrupt to external code, library, etc. but then it does depend on how (or if) that library handles interrupts (e.g. cleaning-up itself), etc.

anyway, since I don't know enough how julia handles the interrupts to answer the questions, It's safest to revert this thing as it breaks something that used to work without achieving what we want in return;

let's keep this open for the time as a remainder though

@benlorenz
Copy link
Member Author

julia> using Polymake
...
julia> sleep(10)
^CERROR: InterruptException:
Stacktrace:
 [1] wait at ./asyncevent.jl:128 [inlined]
 [2] sleep(::Int64) at ./asyncevent.jl:213
 [3] top-level scope at REPL[2]:1

julia> c = polytope.cube(14);

julia> c.VERTICES;
^CERROR: InterruptException:
Stacktrace:
 [1] internal_give(::Polymake.BigObjectAllocated, ::String) at /home/lorenz/.julia/packages/CxxWrap/ucmly/src/CxxWrap.jl:596
 [2] give(::Polymake.BigObjectAllocated, ::String) at /home/lorenz/software/polymake/julia/Polymake-glibcxx.jl/src/perlobj.jl:41
 [3] getproperty(::Polymake.BigObjectAllocated, ::Symbol) at /home/lorenz/software/polymake/julia/Polymake-glibcxx.jl/src/perlobj.jl:53

julia> c
Error showing value of type Polymake.BigObjectAllocated:
ERROR: rule 'RAYS, LINEALITY_SPACE : FACETS, LINEAR_SPAN, RAYS_IN_FACETS' attempts to read its output property VERTICES before it is created

Stacktrace:
 [1] properties(::Polymake.BigObjectAllocated) at /home/lorenz/.julia/packages/CxxWrap/ucmly/src/CxxWrap.jl:596
 [2] show(::IOContext{REPL.Terminals.TTYTerminal}, ::MIME{Symbol("text/plain")}, ::Polymake.BigObjectAllocated) at /home/lorenz/software/polymake/julia/Polymake-glibcxx.jl/src/visual.jl:4
 [3] display(::REPL.REPLDisplay, ::MIME{Symbol("text/plain")}, ::Any) at /var/tmp/portage/dev-lang/julia-1.4.0-r1/work/julia-1.4.0/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:137
 [4] display(::REPL.REPLDisplay, ::Any) at /var/tmp/portage/dev-lang/julia-1.4.0-r1/work/julia-1.4.0/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:141
 [5] display(::Any) at ./multimedia.jl:323
 [6] #invokelatest#1 at ./essentials.jl:712 [inlined]
 [7] invokelatest at ./essentials.jl:711 [inlined]
 [8] print_response(::IO, ::Any, ::Bool, ::Bool, ::Any) at /var/tmp/portage/dev-lang/julia-1.4.0-r1/work/julia-1.4.0/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:161
 [9] print_response(::REPL.AbstractREPL, ::Any, ::Bool, ::Bool) at /var/tmp/portage/dev-lang/julia-1.4.0-r1/work/julia-1.4.0/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:146
 [10] (::REPL.var"#do_respond#38"{Bool,REPL.var"#48#57"{REPL.LineEditREPL,REPL.REPLHistoryProvider},REPL.LineEditREPL,REPL.LineEdit.Prompt})(::Any, ::Any, ::Any) at /var/tmp/portage/dev-lang/julia-1.4.0-r1/work/julia-1.4.0/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:729

julia> exit()

signal (11): Segmentation fault
in expression starting at REPL[6]:1
Segmentation fault

@benlorenz benlorenz modified the milestones: 0.3.3, 0.4.0 Apr 16, 2020
@benlorenz
Copy link
Member Author

I hope to get this done tonight so we can do a release tomorrow.

benlorenz added a commit that referenced this issue Apr 21, 2020
dont capture sigint from polymake (as it completely blocks it for julia)
use different signal for initalization of polymake Main.pm (otherwise julia terminates instantly on ctrl+c)
warn on ctrl+c during polymake computation

fixes #233
@kalmarek kalmarek removed this from the 0.4.0 milestone Apr 23, 2020
@kalmarek kalmarek reopened this Apr 23, 2020
@kalmarek
Copy link
Contributor

since we can't interrupt polymake we should disable_sigint before every function/method/give call:

help?> disable_sigint
search: disable_sigint

  disable_sigint(f::Function)

  Disable Ctrl-C handler during execution of a function on the current task, for calling external code that may call julia code that is not interrupt safe. Intended to be called using do
  block syntax as follows:

  disable_sigint() do
      # interrupt-unsafe code
      ...
  end

  This is not needed on worker threads (Threads.threadid() != 1) since the InterruptException will only be delivered to the master thread. External functions that do not call julia code
  or julia runtime automatically disable sigint during their execution.

This won't solve the original issue, but

  • we can't fix it in Polymake.jl alone;
  • we will avoid the forest of memory corruption in the valley of segfaults

Maybe polymake itself could learn when it is safe to interrupt it, but I understand this is a HUGE endeavour.

@benlorenz
Copy link
Member Author

since we can't interrupt polymake we should disable_sigint before every function/method/give call:

This seems very reasonable. In theory we might need to do this for any small cxxwrap based function call?

Is it possible to get some custom handler running in this case so that we can pass a different signal to polymake which can abort at least some (e.g. perl-based) computations?

jl_install_sigint_handler won't help I guess ...

Maybe polymake itself could learn when it is safe to interrupt it, but I understand this is a HUGE endeavour.

It does know that it's safe during perl code. There is https://trac.polymake.org/ticket/20 open for quite a while

@kalmarek
Copy link
Contributor

kalmarek commented May 6, 2020

in #278 we disable sigint while calling into polymake kernel

@benlorenz
Copy link
Member Author

benlorenz commented Jun 3, 2020

We had a request to add a (non-exported) flag that disables this feature (disables the disable_sigint) for very adventurous developers (with a big warning).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants