aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/os/exec_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/os/exec_linux.go')
-rw-r--r--src/os/exec_linux.go103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/os/exec_linux.go b/src/os/exec_linux.go
new file mode 100644
index 000000000..58ee79cc8
--- /dev/null
+++ b/src/os/exec_linux.go
@@ -0,0 +1,103 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build linux && !baremetal && !tinygo.wasm
+
+package os
+
+import (
+ "errors"
+ "runtime"
+ "syscall"
+)
+
+// The only signal values guaranteed to be present in the os package on all
+// systems are os.Interrupt (send the process an interrupt) and os.Kill (force
+// the process to exit). On Windows, sending os.Interrupt to a process with
+// os.Process.Signal is not implemented; it will return an error instead of
+// sending a signal.
+var (
+ Interrupt Signal = syscall.SIGINT
+ Kill Signal = syscall.SIGKILL
+)
+
+// Keep compatible with golang and always succeed and return new proc with pid on Linux.
+func findProcess(pid int) (*Process, error) {
+ return &Process{Pid: pid}, nil
+}
+
+func (p *Process) release() error {
+ // NOOP for unix.
+ p.Pid = -1
+ // no need for a finalizer anymore
+ runtime.SetFinalizer(p, nil)
+ return nil
+}
+
+// This function is a wrapper around the forkExec function, which is a wrapper around the fork and execve system calls.
+// The StartProcess function creates a new process by forking the current process and then calling execve to replace the current process with the new process.
+// It thereby replaces the newly created process with the specified command and arguments.
+// Differences to upstream golang implementation (https://cs.opensource.google/go/go/+/master:src/syscall/exec_unix.go;l=143):
+// * No setting of Process Attributes
+// * Ignoring Ctty
+// * No ForkLocking (might be introduced by #4273)
+// * No parent-child communication via pipes (TODO)
+// * No waiting for crashes child processes to prohibit zombie process accumulation / Wait status checking (TODO)
+func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
+ if argv == nil {
+ return 0, errors.New("exec: no argv")
+ }
+
+ if len(argv) == 0 {
+ return 0, errors.New("exec: no argv")
+ }
+
+ if attr == nil {
+ attr = new(ProcAttr)
+ }
+
+ p, err := fork()
+ pid = int(p)
+
+ if err != nil {
+ return 0, err
+ }
+
+ // else code runs in child, which then should exec the new process
+ err = execve(argv0, argv, attr.Env)
+ if err != nil {
+ // exec failed
+ return 0, err
+ }
+ // 3. TODO: use pipes to communicate back child status
+ return pid, nil
+}
+
+// In Golang, the idiomatic way to create a new process is to use the StartProcess function.
+// Since the Model of operating system processes in tinygo differs from the one in Golang, we need to implement the StartProcess function differently.
+// The startProcess function is a wrapper around the forkExec function, which is a wrapper around the fork and execve system calls.
+// The StartProcess function creates a new process by forking the current process and then calling execve to replace the current process with the new process.
+// It thereby replaces the newly created process with the specified command and arguments.
+func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
+ if attr != nil {
+ if attr.Dir != "" {
+ return nil, ErrNotImplementedDir
+ }
+
+ if attr.Sys != nil {
+ return nil, ErrNotImplementedSys
+ }
+
+ if len(attr.Files) != 0 {
+ return nil, ErrNotImplementedFiles
+ }
+ }
+
+ pid, err := forkExec(name, argv, attr)
+ if err != nil {
+ return nil, err
+ }
+
+ return findProcess(pid)
+}