-
Notifications
You must be signed in to change notification settings - Fork 915
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add StartProcess functionality (fix)
- Loading branch information
Showing
6 changed files
with
170 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// 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 posix || aix || linux || dragonfly || freebsd || (js && wasm) || netbsd || openbsd || solaris || wasip1 | ||
// +build posix aix linux dragonfly freebsd js,wasm netbsd openbsd solaris wasip1 | ||
|
||
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) { | ||
var ( | ||
ret uintptr | ||
) | ||
|
||
if len(argv) == 0 { | ||
return 0, errors.New("exec: no argv") | ||
} | ||
|
||
if attr == nil { | ||
attr = new(ProcAttr) | ||
} | ||
|
||
argv0p, err := syscall.BytePtrFromString(argv0) | ||
if err != nil { | ||
return 0, err | ||
} | ||
argvp, err := syscall.SlicePtrFromStrings(argv) | ||
if err != nil { | ||
return 0, err | ||
} | ||
envp, err := syscall.SlicePtrFromStrings(attr.Env) | ||
if err != nil { | ||
return 0, err | ||
} | ||
|
||
if (runtime.GOOS == "freebsd" || runtime.GOOS == "dragonfly") && len(argv) > 0 && len(argv[0]) > len(argv0) { | ||
argvp[0] = argv0p | ||
} | ||
|
||
pid = syscall.Fork() | ||
if ret < 0 { | ||
return 0, errors.New("fork failed") | ||
} | ||
|
||
if ret != 0 { | ||
// if fd == 0 code runs in parent | ||
return int(ret), nil | ||
} else { | ||
// else code runs in child, which then should exec the new process | ||
ret = syscall.Execve(argv0, argv, envp) | ||
if ret != 0 { | ||
// exec failed | ||
syscall.Exit(1) | ||
} | ||
// 3. TODO: use pipes to communicate back child status | ||
return int(ret), 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) { | ||
pid, err := ForkExec(name, argv, attr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return findProcess(pid) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
//go:build !aix && !android && !freebsd && !linux && !netbsd && !openbsd && !plan9 && !solaris | ||
// +build !aix,!android,!freebsd,!linux,!netbsd,!openbsd,!plan9,!solaris | ||
|
||
package os | ||
|
||
func findProcess(pid int) (*Process, error) { | ||
return &Process{Pid: pid}, nil | ||
} | ||
|
||
func (p *Process) release() error { | ||
p.Pid = -1 | ||
return nil | ||
} | ||
|
||
func forkExec(_ string, _ []string, _ *ProcAttr) (pid int, err error) { | ||
return 0, ErrNotImplemented | ||
} | ||
|
||
func startProcess(_ string, _ []string, _ *ProcAttr) (proc *Process, err error) { | ||
return &Process{Pid: 0}, ErrNotImplemented | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package os_test | ||
|
||
import ( | ||
. "os" | ||
"runtime" | ||
"testing" | ||
) | ||
|
||
// Test the functionality of the forkExec function, which is used to fork and exec a new process. | ||
// This test is not run on Windows, as forkExec is not supported on Windows. | ||
// This test is not run on Plan 9, as forkExec is not supported on Plan 9. | ||
func TestForkExec(t *testing.T) { | ||
if runtime.GOOS != "linux" { | ||
t.Logf("skipping test on %s", runtime.GOOS) | ||
return | ||
} | ||
|
||
proc, err := StartProcess("echo", []string{"echo", "hello", "world"}, &ProcAttr{}) | ||
if err != nil { | ||
t.Fatalf("forkExec failed: %v", err) | ||
return | ||
} | ||
|
||
if proc.Pid == 0 { | ||
t.Fatalf("forkExec failed: new process has pid 0") | ||
} else { | ||
t.Logf("forkExec succeeded: new process has pid %d", proc) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
//go:build unix | ||
|
||
package syscall | ||
|
||
// Implemented in runtime package. | ||
func runtime_BeforeExec() | ||
func runtime_AfterExec() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
//go:build linux || unix | ||
// +build linux unix | ||
|
||
package syscall | ||
|
||
import "errors" | ||
|