The OS which tries to "block" signals while their handlers are executing. I 
think the `raise` inside the handler confuses your OS into thinking the handler 
has not yet returned. So, changing your `handler` to this works on Unix to 
unblock SIGINT, the Ctrl-C signal: 
    
    
    import posix
    proc handler() {.noconv.} =
      var nmask, omask: Sigset
      discard sigemptyset(nmask)
      discard sigemptyset(omask)
      discard sigaddset(nmask, SIGINT)
      if sigprocmask(SIG_UNBLOCK, nmask, omask) == -1:
        raiseOSError(osLastError())
      raise newException(EKeyboardInterrupt, "Keyboard Interrupt")
    
    
    Run

You probably also should re-call `setControlCHook(handler)` in your `else` 
clause after your echo. IIRC, the `signal` call Nim uses will (often but not 
portably!) just revert back to the default action which for `SIGINT` is to die 
(although, the way things sound like they are working for you, that reversion 
may never happen).

If you need something more portable then you might do better to manage the 
state from inside the signal handler rather than mixing signals & exceptions. 
E.g.: 
    
    
    import times, os, strutils
    
    let t = epochTime()
    var caught = false
    
    proc handler() {.noconv.} =
      if caught:
        echo "Caught a second time"
        quit()
      caught = true
      echo "Program has run for ", formatFloat(epochTime() - t, precision = 0), 
" seconds."
    
    setControlCHook(handler)
    
    for n in 1..<int64.high:
      sleep 500
      echo n
    
    
    Run

You could just add some `if caught: setControlCHook(handler); clearInput()` 
wherever you wanted to clear the input on that first Ctrl-C.

It might be possible to put the re-install of the signal handler in `handler` 
itself rather than externally in both cases, though I also would bet this is 
not portable/reliable/fully defined. POSIX tried to clean up all this `signal` 
stuff with `sigaction` and friends (which that `sigprocmask` is a part of), but 
Nim tries to only use ANSI C things and work both on Unix & Windows. So, the 
best answer to your question probably depends upon whether you seek 
cross-platform portability of Control-C handling or if Unix alone is good 
enough.

Reply via email to