Skip to content

Instantly share code, notes, and snippets.

@dom96
Created April 7, 2011 21:32
Show Gist options
  • Save dom96/908782 to your computer and use it in GitHub Desktop.
Save dom96/908782 to your computer and use it in GitHub Desktop.
## Module for handling and raising signals. Wraps ``<signals.h>``.
type
TSignal = enum
SIGINT = 2
proc signal*(sig: cint, func: pointer) {.importc: "signal", header: "<signal.h>".}
template atSignal*(s: TSignal, actions: stmt): stmt =
proc callback(sig: cint) =
actions
signal(int(s), callback)
when isMainModule:
atSignal(SIGINT):
echo("Called back!")
quit()
while True:
nil
@kaushalmodi
Copy link

kaushalmodi commented May 3, 2019

Here's a working version of above code on Nim devel as of 2019/05/02:

# https://gist.github.com/dom96/908782

## Module for handling and raising signals. Wraps ``<signals.h>``.

# https://en.wikipedia.org/wiki/Signal_(IPC)#POSIX_signals
type
  TSignal = enum
    SIGINT = 2
    SIGSomething3 # avoiding enum with holes
    SIGSomething4
    SIGSomething5
    SIGSomething6
    SIGSomething7
    SIGFPE

proc signal*(sig: cint, fn: pointer) {.importc: "signal", header: "<signal.h>".}

template atSignal*(s: TSignal, actions: untyped): untyped =
  proc callback(sig: cint) =
    actions
  signal(cint(s), callback)

# Hit Ctrl+C to kill the run
when isMainModule:
  atSignal(SIGINT):
    echo("\nYou pressed Ctrl+C!!")
    quit()
  while true:
    discard

@kaushalmodi
Copy link

kaushalmodi commented May 3, 2019

Here's the same example using sigaction instead of signal, and using the Nim posix module. I learn that signal is deprecated and sigaction should be used instead:

import posix

type
  StdSignal* = enum
    SIGHUP = 1       ##  1. Hangup
    SIGINT           ##  2. Terminal interrupt signal

# https://gist.github.com/dom96/908782
template onSignal*(sigs: varargs[StdSignal]; actions: untyped): untyped =
  # https://www.gnu.org/software/libc/manual/html_node/Sigaction-Function-Example.html#Sigaction-Function-Example
  proc newHandler(signum: cint) {.noconv.} =
    echo "\n[Error] Standard signal " & $StdSignal(signum) & " detected"
    `actions`

  var
    newAction: SigAction
  newAction.sa_handler = newHandler
  discard sigemptyset(newAction.sa_mask)
  newAction.sa_flags = 0

  for sig in sigs:
    discard sigaction(cint(sig), newAction, nil)

when isMainModule:
  onSignal(SIGFPE, SIGINT):
    quit()

  echo "Hit Ctrl-C to end this program .."
  discard pause() # Hang the program over here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment