Skip to content

Commit 828ca6a

Browse files
committed
add signal stubs in runtime
Signed-off-by: leongross <[email protected]>
1 parent 336b9b3 commit 828ca6a

File tree

6 files changed

+168
-0
lines changed

6 files changed

+168
-0
lines changed

GNUmakefile

+1
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ TEST_PACKAGES_FAST = \
335335
net/http/internal/ascii \
336336
net/mail \
337337
os \
338+
os/signal \
338339
path \
339340
reflect \
340341
sync \

src/os/exec.go

+4
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

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2012 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 !plan9 && !windows && !js && !wasm && !wasip1 && !wasip2
6+
// +build !plan9,!windows,!js,!wasm,!wasip1,!wasip2
7+
8+
package signal
9+
10+
import (
11+
"os"
12+
"syscall"
13+
)
14+
15+
const (
16+
numSig = 65 // max across all systems
17+
)
18+
19+
type Signal interface {
20+
String() string
21+
Signal() // to distinguish from other Stringers
22+
}
23+
24+
// Defined by the runtime package and used by syscall/sigqueue.go.
25+
func signal_disable(uint32)
26+
func signal_enable(uint32)
27+
func signal_ignore(uint32)
28+
func signal_ignored(uint32) bool
29+
func signal_recv() uint32
30+
31+
func signum(sig os.Signal) int {
32+
switch sig := sig.(type) {
33+
case syscall.Signal:
34+
i := int(sig)
35+
if i < 0 || i >= numSig {
36+
return -1
37+
}
38+
return i
39+
default:
40+
return -1
41+
}
42+
}
43+
44+
func enableSignal(sig int) {
45+
signal_enable(uint32(sig))
46+
}
47+
48+
func disableSignal(sig int) {
49+
signal_disable(uint32(sig))
50+
}
51+
52+
func ignoreSignal(sig int) {
53+
signal_ignore(uint32(sig))
54+
}

src/os/signal/signal_linux_test.go

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//go:build !plan9 && !windows && !js && !wasm && !wasip1 && !wasip2
2+
// +build !plan9,!windows,!js,!wasm,!wasip1,!wasip2
3+
4+
package signal
5+
6+
import (
7+
"runtime"
8+
"testing"
9+
)
10+
11+
// The file sigqueue.go contains preliminary stubs for signal handling.
12+
// Since tinygo ultimately lacks support for signals, these stubs are
13+
// placeholders for future work.
14+
// There might be userland applications that rely on these functions
15+
// from the upstream go package os/signal that we want to enable
16+
// building and linking.
17+
18+
func TestSignalHandling(t *testing.T) {
19+
if runtime.GOOS == "wasip1" || runtime.GOOS == "wasip2" {
20+
t.Skip()
21+
}
22+
23+
// This test is a placeholder for future work.
24+
// It is here to ensure that the stubs in sigqueue.go
25+
// are correctly linked and can be called from userland
26+
// applications.
27+
enableSignal(0)
28+
disableSignal(0)
29+
ignoreSignal(0)
30+
}

src/runtime/sigqueue.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2009 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 !plan9
6+
// +build !plan9
7+
8+
package runtime
9+
10+
// Stub definitions copied from upstream golang
11+
// TODO: implement a minimal functional version of these functions
12+
13+
// go: linkname os/signal.signal_disable signal_disable
14+
func signal_disable(_ uint32) {}
15+
16+
// go: linkname os/signal.signal_enable signal_enable
17+
func signal_enable(_ uint32) {}
18+
19+
// go: linkname os/signal.signal_ignore signal_ignore
20+
func signal_ignore(_ uint32) {}
21+
22+
// go: linkname os/signal.signal_ignored signal_ignored
23+
func signal_ignored(_ uint32) bool { return true }
24+
25+
// go: linkname os/signal.signal_recv signal_recv
26+
func signal_recv() uint32 { return 0 }

src/syscall/syscall_unix.go

+53
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package syscall
22

3+
import "errors"
4+
35
func Exec(argv0 string, argv []string, envv []string) (err error)
46

57
// The two SockaddrInet* structs have been copied from the Go source tree.
@@ -16,3 +18,54 @@ type SockaddrInet6 struct {
1618
Addr [16]byte
1719
raw RawSockaddrInet6
1820
}
21+
22+
func Fork() (err error) {
23+
fail := int(libc_fork())
24+
if fail < 0 {
25+
// TODO: parse the syscall return codes
26+
return errors.New("fork failed")
27+
}
28+
return
29+
}
30+
31+
// the golang standard library does not expose interfaces for execve and fork, so we define them here the same way via the libc wrapper
32+
func Execve(pathname string, argv []string, envv []string) (err error) {
33+
argv0 := cstring(pathname)
34+
35+
// transform argv and envv into the format expected by execve
36+
argv1 := make([]*byte, len(argv)+1)
37+
for i, arg := range argv {
38+
argv1[i] = &cstring(arg)[0]
39+
}
40+
argv1[len(argv)] = nil
41+
42+
env1 := make([]*byte, len(envv)+1)
43+
for i, env := range envv {
44+
env1[i] = &cstring(env)[0]
45+
}
46+
env1[len(envv)] = nil
47+
48+
fail := int(libc_execve(&argv0[0], &argv1[0], &env1[0]))
49+
if fail < 0 {
50+
// TODO: parse the syscall return codes
51+
return errors.New("fork failed")
52+
}
53+
return
54+
}
55+
56+
func cstring(s string) []byte {
57+
data := make([]byte, len(s)+1)
58+
copy(data, s)
59+
// final byte should be zero from the initial allocation
60+
return data
61+
}
62+
63+
// pid_t fork(void);
64+
//
65+
//export fork
66+
func libc_fork() int32
67+
68+
// int execve(const char *filename, char *const argv[], char *const envp[]);
69+
//
70+
//export execve
71+
func libc_execve(filename *byte, argv **byte, envp **byte) int

0 commit comments

Comments
 (0)