Skip to content

Commit f7bd438

Browse files
committed
add signal.Ignore, add signal.Ignored, update signal tests, add Exited()
Signed-off-by: leongross <leon.gross@9elements.com>
1 parent 22ec604 commit f7bd438

File tree

5 files changed

+95
-9
lines changed

5 files changed

+95
-9
lines changed

src/os/exec.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ func (p *ProcessState) Sys() interface{} {
4747
return nil // TODO
4848
}
4949

50+
func (p *ProcessState) Exited() bool {
51+
return false // TODO
52+
}
53+
5054
// ExitCode returns the exit code of the exited process, or -1
5155
// if the process hasn't exited or was terminated by a signal.
5256
func (p *ProcessState) ExitCode() int {

src/os/signal/signal_linux.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go: build linux
6+
7+
package signal
8+
9+
import (
10+
"os"
11+
"syscall"
12+
)
13+
14+
// these functions are linked to the runtime at src/runtime/runtime_unix.go
15+
func signal_enable(sig uint32)
16+
func signal_disable(sig uint32)
17+
func signal_ignore(sig uint32)
18+
func signal_ignored() []bool
19+
20+
func signum(s os.Signal) int {
21+
return int(s.(syscall.Signal))
22+
}
23+
24+
// Ignore causes the provided signals to be ignored.
25+
// If they are received by the program, nothing will happen
26+
func Ignore(sig ...os.Signal) {
27+
for _, s := range sig {
28+
signal_ignore(uint32(signum(s)))
29+
}
30+
}
31+
32+
// Return true if the provided signal is being ignored
33+
// The runtime keeps track of the ignored signals in the signalIgnored array
34+
func Ignored(sig os.Signal) bool {
35+
return signal_ignored()[signum(sig)]
36+
}
37+
38+
// TODO: reset all previously set masks
39+
func Reset(sig ...os.Signal) {}

src/runtime/runtime_unix.go

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
package runtime
44

55
import (
6-
"syscall"
76
"unsafe"
87
)
98

@@ -318,7 +317,17 @@ func init() {
318317
}
319318

320319
var signalChan chan uint32
321-
var signalIgnored []bool // TODO: replace with more efficient bitmap?
320+
var signalIgnored []bool
321+
322+
// SignalIgnored returns the signalIgnored array.
323+
// Do not expose signalIgnored directly, as it is mutable.
324+
//
325+
//export SignalIgnored
326+
func SignalIgnored() []bool {
327+
sigs := make([]bool, len(signalIgnored))
328+
copy(sigs, signalIgnored)
329+
return sigs
330+
}
322331

323332
//go:linkname signal_enable os/signal.signal_enable
324333
func signal_enable(sig uint32) {
@@ -329,6 +338,7 @@ func signal_enable(sig uint32) {
329338
//export tinygo_signal_enable
330339
func tinygo_signal_enable(s uint32)
331340

341+
// go: link signal_disable os/signal.signal_disable
332342
func signal_disable(sig uint32) {
333343
tinygo_signal_disable(sig)
334344
}
@@ -339,10 +349,22 @@ func tinygo_signal_disable(sig uint32)
339349
// Ignore the given signal by adding it into the signalIgnored array.
340350
// If the signal is received, it will be ignored in the tinygo_signal_handler.
341351
// The signals SIGKILL and SIGSTOP cannot be caught or ignored. man (2) signal
342-
func tinygo_signal_ignore(sig uint32) {
343-
if syscall.Signal(sig) != syscall.SIGKILL && syscall.Signal(sig) != syscall.SIGSTOP {
344-
signalIgnored[sig] = true
345-
}
352+
//
353+
// func tinygo_signal_ignore(sig uint32) {
354+
// if syscall.Signal(sig) != syscall.SIGKILL && syscall.Signal(sig) != syscall.SIGSTOP {
355+
// signalIgnored[sig] = true
356+
// }
357+
// }
358+
359+
//export tinygo_signal_ignore
360+
func tinygo_signal_ignore(sig uint32)
361+
362+
// go: link signal_ignore os/signal.signal_ignore
363+
func signal_ignore(sig uint32) {
364+
// keep track of ignored signal for Ignore(sig os.Signal)
365+
// the ignore logic itself is tracked by the kernel https://elixir.bootlin.com/linux/v6.10/source/kernel/signal.c#L4142
366+
signalIgnored[sig] = true
367+
tinygo_signal_ignore(sig)
346368
}
347369

348370
// void tinygo_signal_handler(int sig);

src/runtime/signal.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// go:build none
1+
//go:build none
22

33
// Ignore the //go:build above. This file is manually included on Linux and
44
// MacOS to provide os/signal support.
@@ -31,3 +31,11 @@ void tinygo_signal_disable(uint32_t sig)
3131
act.sa_handler = SIG_DFL;
3232
sigaction(sig, &act, NULL);
3333
}
34+
35+
// Ignore a signal from the runtime.
36+
void tinygo_signal_ignore(uint32_t sig)
37+
{
38+
struct sigaction act = {0};
39+
act.sa_handler = SIG_IGN;
40+
sigaction(sig, &act, NULL);
41+
}

testdata/signal/signal.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,23 @@ func main() {
2525
}
2626
}
2727
}()
28+
// test signal_enable
2829

29-
// Send the signal.
30-
syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
30+
// test signal_disable
31+
32+
// test signal_ignore
33+
signal.Ignore(syscall.SIGUSR1)
34+
if signal.Ignored(syscall.SIGUSR1) {
35+
println("SIGUSR1 is ignored")
36+
} else {
37+
println("SIGUSR1 is not ignored")
38+
}
3139

40+
// test signal_ignore SIGKILL and SIGSTOP that cannot be caught or ignored
41+
signal.Ignore()
42+
43+
// send the signal.
44+
syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
3245
time.Sleep(time.Millisecond * 100)
3346
println("exiting signal program")
3447
}

0 commit comments

Comments
 (0)