Support System.Signal for node backend (#2556)

* first pass at signal support for node backend

* change signal values to int's

* implements defaultSignal

* return -1 as expected by calling API if any error is raised by nodejs runtime

* finishes signal support for nodejs

* extract repetitive foreign import identifiers

* fix comments
This commit is contained in:
ProofOfKeags 2022-07-10 03:18:58 -06:00 committed by GitHub
parent 8658351b94
commit 68a144bf18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 125 additions and 0 deletions

View File

@ -16,37 +16,50 @@ import System.Errno
signalFFI : String -> String
signalFFI fn = "C:" ++ fn ++ ", libidris2_support, idris_signal.h"
signalFFINode : String -> String
signalFFINode fn = "node:support:" ++ fn ++ ",support_system_signal"
--
-- Signals
--
%foreign signalFFI "sighup"
signalFFINode "sighup"
prim__sighup : Int
%foreign signalFFI "sigint"
signalFFINode "sigint"
prim__sigint : Int
%foreign signalFFI "sigabrt"
signalFFINode "sigabrt"
prim__sigabrt : Int
%foreign signalFFI "sigquit"
signalFFINode "sigquit"
prim__sigquit : Int
%foreign signalFFI "sigill"
signalFFINode "sigill"
prim__sigill : Int
%foreign signalFFI "sigsegv"
signalFFINode "sigsegv"
prim__sigsegv : Int
%foreign signalFFI "sigtrap"
signalFFINode "sigtrap"
prim__sigtrap : Int
%foreign signalFFI "sigfpe"
signalFFINode "sigfpe"
prim__sigfpe : Int
%foreign signalFFI "sigusr1"
signalFFINode "sigusr1"
prim__sigusr1 : Int
%foreign signalFFI "sigusr2"
signalFFINode "sigusr2"
prim__sigusr2 : Int
public export
@ -126,21 +139,27 @@ toSignal x = lookup x codes
-- Signal Handling
--
%foreign signalFFI "ignore_signal"
signalFFINode "ignoreSignal"
prim__ignoreSignal : Int -> PrimIO Int
%foreign signalFFI "default_signal"
signalFFINode "defaultSignal"
prim__defaultSignal : Int -> PrimIO Int
%foreign signalFFI "collect_signal"
signalFFINode "collectSignal"
prim__collectSignal : Int -> PrimIO Int
%foreign signalFFI "handle_next_collected_signal"
signalFFINode "handleNextCollectedSignal"
prim__handleNextCollectedSignal : PrimIO Int
%foreign signalFFI "send_signal"
signalFFINode "sendSignal"
prim__sendSignal : Int -> Int -> PrimIO Int
%foreign signalFFI "raise_signal"
signalFFINode "raiseSignal"
prim__raiseSignal : Int -> PrimIO Int
||| An Error represented by a code. See

View File

@ -0,0 +1,106 @@
const support_system_signal_process = require('process')
// https://en.wikipedia.org/wiki/Signal_(IPC)#Default_action
const support_system_signal_sighup = 1
const support_system_signal_sigint = 2
const support_system_signal_sigquit = 3
const support_system_signal_sigill = 4
const support_system_signal_sigtrap = 5
const support_system_signal_sigabrt = 6
const support_system_signal_sigfpe = 8
const support_system_signal_sigusr1 = 10
const support_system_signal_sigsegv = 11
const support_system_signal_sigusr2 = 12
function signal_int_to_string(signal) {
switch (signal) {
case 1:
return 'SIGHUP'
case 2:
return 'SIGINT'
case 3:
return 'SIGQUIT'
case 4:
return 'SIGILL'
case 5:
return 'SIGTRAP'
case 6:
return 'SIGABRT'
case 8:
return 'SIGFPE'
case 10:
return 'SIGUSR1'
case 11:
return 'SIGSEGV'
case 12:
return 'SIGUSR2'
default:
// https://nodejs.org/api/process.html#signal-events
// 0 can be sent to test for the existence of a process, it has no effect if the process exists, but will throw an error if the process does not exist.
return 0
}
}
function support_system_signal_ignoreSignal(signal) {
let signal_string = signal_int_to_string(signal)
try {
support_system_signal_process.on(signal_string, sig => {})
return 0
} catch (e) {
return -1
}
}
function support_system_signal_sendSignal(pid, signal) {
let signal_string = signal_int_to_string(signal)
try {
support_system_signal_process.kill(pid, signal_string)
return 0
} catch (e) {
return -1
}
}
function support_system_signal_raiseSignal(signal) {
let signal_string = signal_int_to_string(signal)
try {
support_system_signal_process.kill(support_system_signal_process.pid, signal_string)
return 0
} catch (e) {
return -1
}
}
function support_system_signal_defaultSignal(signal) {
let signal_string = signal_int_to_string(signal)
try {
support_system_signal_process.removeAllListeners(signal_string)
return 0
} catch (e) {
return -1
}
}
// this implementation deduplicates signals and leaves handle ordering up to details of the Map impl
var pending_signals = new Map();
function support_system_signal_collectSignal(signal) {
let signal_string = system_signal_int_to_string(signal)
try {
support_system_signal_process.on(signal_string, x => { pending_signals.set(signal) })
return 0
} catch (e) {
return -1
}
}
function support_system_signal_handleNextCollectedSignal() {
let next = pending_signals.keys().next()
if (next.done) {
return -1
} else {
let val = next.value
pending_signals.delete(val)
return val
}
}