4
.github/workflows/go.yml
vendored
4
.github/workflows/go.yml
vendored
@@ -14,8 +14,8 @@ jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
# os: [macos-latest, ubuntu-latest]
|
||||
os: [macos-latest]
|
||||
os: [macos-latest, ubuntu-latest]
|
||||
# os: [macos-latest]
|
||||
llvm: [18]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
||||
152
c/libuv/error.go
152
c/libuv/error.go
@@ -9,85 +9,85 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
E2BIG Errno = Errno(syscall.E2BIG)
|
||||
EACCES Errno = Errno(syscall.EACCES)
|
||||
EADDRINUSE Errno = Errno(syscall.EADDRINUSE)
|
||||
EADDRNOTAVAIL Errno = Errno(syscall.EADDRNOTAVAIL)
|
||||
EAFNOSUPPORT Errno = Errno(syscall.EAFNOSUPPORT)
|
||||
EAGAIN Errno = Errno(syscall.EAGAIN)
|
||||
EALREADY Errno = Errno(syscall.EALREADY)
|
||||
EBADF Errno = Errno(syscall.EBADF)
|
||||
EBUSY Errno = Errno(syscall.EBUSY)
|
||||
ECANCELED Errno = Errno(syscall.ECANCELED)
|
||||
ECONNABORTED Errno = Errno(syscall.ECONNABORTED)
|
||||
ECONNREFUSED Errno = Errno(syscall.ECONNREFUSED)
|
||||
ECONNRESET Errno = Errno(syscall.ECONNRESET)
|
||||
EDESTADDRREQ Errno = Errno(syscall.EDESTADDRREQ)
|
||||
EEXIST Errno = Errno(syscall.EEXIST)
|
||||
EFAULT Errno = Errno(syscall.EFAULT)
|
||||
EFBIG Errno = Errno(syscall.EFBIG)
|
||||
EHOSTUNREACH Errno = Errno(syscall.EHOSTUNREACH)
|
||||
EINTR Errno = Errno(syscall.EINTR)
|
||||
EINVAL Errno = Errno(syscall.EINVAL)
|
||||
EIO Errno = Errno(syscall.EIO)
|
||||
EISCONN Errno = Errno(syscall.EISCONN)
|
||||
EISDIR Errno = Errno(syscall.EISDIR)
|
||||
ELOOP Errno = Errno(syscall.ELOOP)
|
||||
EMFILE Errno = Errno(syscall.EMFILE)
|
||||
EMSGSIZE Errno = Errno(syscall.EMSGSIZE)
|
||||
ENAMETOOLONG Errno = Errno(syscall.ENAMETOOLONG)
|
||||
ENETDOWN Errno = Errno(syscall.ENETDOWN)
|
||||
ENETUNREACH Errno = Errno(syscall.ENETUNREACH)
|
||||
ENFILE Errno = Errno(syscall.ENFILE)
|
||||
ENOBUFS Errno = Errno(syscall.ENOBUFS)
|
||||
ENODEV Errno = Errno(syscall.ENODEV)
|
||||
ENOENT Errno = Errno(syscall.ENOENT)
|
||||
ENOMEM Errno = Errno(syscall.ENOMEM)
|
||||
ENOPROTOOPT Errno = Errno(syscall.ENOPROTOOPT)
|
||||
ENOSPC Errno = Errno(syscall.ENOSPC)
|
||||
ENOSYS Errno = Errno(syscall.ENOSYS)
|
||||
ENOTCONN Errno = Errno(syscall.ENOTCONN)
|
||||
ENOTDIR Errno = Errno(syscall.ENOTDIR)
|
||||
ENOTEMPTY Errno = Errno(syscall.ENOTEMPTY)
|
||||
ENOTSOCK Errno = Errno(syscall.ENOTSOCK)
|
||||
ENOTSUP Errno = Errno(syscall.ENOTSUP)
|
||||
EOVERFLOW Errno = Errno(syscall.EOVERFLOW)
|
||||
EPERM Errno = Errno(syscall.EPERM)
|
||||
EPIPE Errno = Errno(syscall.EPIPE)
|
||||
EPROTO Errno = Errno(syscall.EPROTO)
|
||||
EPROTONOSUPPORT Errno = Errno(syscall.EPROTONOSUPPORT)
|
||||
EPROTOTYPE Errno = Errno(syscall.EPROTOTYPE)
|
||||
ERANGE Errno = Errno(syscall.ERANGE)
|
||||
EROFS Errno = Errno(syscall.EROFS)
|
||||
ESHUTDOWN Errno = Errno(syscall.ESHUTDOWN)
|
||||
ESPIPE Errno = Errno(syscall.ESPIPE)
|
||||
ESRCH Errno = Errno(syscall.ESRCH)
|
||||
ETIMEDOUT Errno = Errno(syscall.ETIMEDOUT)
|
||||
ETXTBSY Errno = Errno(syscall.ETXTBSY)
|
||||
EXDEV Errno = Errno(syscall.EXDEV)
|
||||
ENXIO Errno = Errno(syscall.ENXIO)
|
||||
EMLINK Errno = Errno(syscall.EMLINK)
|
||||
EHOSTDOWN Errno = Errno(syscall.EHOSTDOWN)
|
||||
ENOTTY Errno = Errno(syscall.ENOTTY)
|
||||
EFTYPE Errno = Errno(syscall.EFTYPE)
|
||||
EILSEQ Errno = Errno(syscall.EILSEQ)
|
||||
ESOCKTNOSUPPORT Errno = Errno(syscall.ESOCKTNOSUPPORT)
|
||||
E2BIG = Errno(syscall.E2BIG)
|
||||
EACCES = Errno(syscall.EACCES)
|
||||
EADDRINUSE = Errno(syscall.EADDRINUSE)
|
||||
EADDRNOTAVAIL = Errno(syscall.EADDRNOTAVAIL)
|
||||
EAFNOSUPPORT = Errno(syscall.EAFNOSUPPORT)
|
||||
EAGAIN = Errno(syscall.EAGAIN)
|
||||
EALREADY = Errno(syscall.EALREADY)
|
||||
EBADF = Errno(syscall.EBADF)
|
||||
EBUSY = Errno(syscall.EBUSY)
|
||||
ECANCELED = Errno(syscall.ECANCELED)
|
||||
ECONNABORTED = Errno(syscall.ECONNABORTED)
|
||||
ECONNREFUSED = Errno(syscall.ECONNREFUSED)
|
||||
ECONNRESET = Errno(syscall.ECONNRESET)
|
||||
EDESTADDRREQ = Errno(syscall.EDESTADDRREQ)
|
||||
EEXIST = Errno(syscall.EEXIST)
|
||||
EFAULT = Errno(syscall.EFAULT)
|
||||
EFBIG = Errno(syscall.EFBIG)
|
||||
EHOSTUNREACH = Errno(syscall.EHOSTUNREACH)
|
||||
EINTR = Errno(syscall.EINTR)
|
||||
EINVAL = Errno(syscall.EINVAL)
|
||||
EIO = Errno(syscall.EIO)
|
||||
EISCONN = Errno(syscall.EISCONN)
|
||||
EISDIR = Errno(syscall.EISDIR)
|
||||
ELOOP = Errno(syscall.ELOOP)
|
||||
EMFILE = Errno(syscall.EMFILE)
|
||||
EMSGSIZE = Errno(syscall.EMSGSIZE)
|
||||
ENAMETOOLONG = Errno(syscall.ENAMETOOLONG)
|
||||
ENETDOWN = Errno(syscall.ENETDOWN)
|
||||
ENETUNREACH = Errno(syscall.ENETUNREACH)
|
||||
ENFILE = Errno(syscall.ENFILE)
|
||||
ENOBUFS = Errno(syscall.ENOBUFS)
|
||||
ENODEV = Errno(syscall.ENODEV)
|
||||
ENOENT = Errno(syscall.ENOENT)
|
||||
ENOMEM = Errno(syscall.ENOMEM)
|
||||
ENOPROTOOPT = Errno(syscall.ENOPROTOOPT)
|
||||
ENOSPC = Errno(syscall.ENOSPC)
|
||||
ENOSYS = Errno(syscall.ENOSYS)
|
||||
ENOTCONN = Errno(syscall.ENOTCONN)
|
||||
ENOTDIR = Errno(syscall.ENOTDIR)
|
||||
ENOTEMPTY = Errno(syscall.ENOTEMPTY)
|
||||
ENOTSOCK = Errno(syscall.ENOTSOCK)
|
||||
ENOTSUP = Errno(syscall.ENOTSUP)
|
||||
EOVERFLOW = Errno(syscall.EOVERFLOW)
|
||||
EPERM = Errno(syscall.EPERM)
|
||||
EPIPE = Errno(syscall.EPIPE)
|
||||
EPROTO = Errno(syscall.EPROTO)
|
||||
EPROTONOSUPPORT = Errno(syscall.EPROTONOSUPPORT)
|
||||
EPROTOTYPE = Errno(syscall.EPROTOTYPE)
|
||||
ERANGE = Errno(syscall.ERANGE)
|
||||
EROFS = Errno(syscall.EROFS)
|
||||
ESHUTDOWN = Errno(syscall.ESHUTDOWN)
|
||||
ESPIPE = Errno(syscall.ESPIPE)
|
||||
ESRCH = Errno(syscall.ESRCH)
|
||||
ETIMEDOUT = Errno(syscall.ETIMEDOUT)
|
||||
ETXTBSY = Errno(syscall.ETXTBSY)
|
||||
EXDEV = Errno(syscall.EXDEV)
|
||||
ENXIO = Errno(syscall.ENXIO)
|
||||
EMLINK = Errno(syscall.EMLINK)
|
||||
EHOSTDOWN = Errno(syscall.EHOSTDOWN)
|
||||
ENOTTY = Errno(syscall.ENOTTY)
|
||||
//EFTYPE = Errno(syscall.EFTYPE)
|
||||
EILSEQ = Errno(syscall.EILSEQ)
|
||||
ESOCKTNOSUPPORT = Errno(syscall.ESOCKTNOSUPPORT)
|
||||
)
|
||||
|
||||
const (
|
||||
EAI_ADDRFAMILY Errno = Errno(net.EAI_ADDRFAMILY)
|
||||
EAI_AGAIN Errno = Errno(net.EAI_AGAIN)
|
||||
EAI_BADFLAGS Errno = Errno(net.EAI_BADFLAGS)
|
||||
EAI_BADHINTS Errno = Errno(net.EAI_BADHINTS)
|
||||
EAI_FAIL Errno = Errno(net.EAI_FAIL)
|
||||
EAI_FAMILY Errno = Errno(net.EAI_FAMILY)
|
||||
EAI_MEMORY Errno = Errno(net.EAI_MEMORY)
|
||||
EAI_NODATA Errno = Errno(net.EAI_NODATA)
|
||||
EAI_NONAME Errno = Errno(net.EAI_NONAME)
|
||||
EAI_OVERFLOW Errno = Errno(net.EAI_OVERFLOW)
|
||||
EAI_PROTOCOL Errno = Errno(net.EAI_PROTOCOL)
|
||||
EAI_SERVICE Errno = Errno(net.EAI_SERVICE)
|
||||
EAI_SOCKTYPE Errno = Errno(net.EAI_SOCKTYPE)
|
||||
EAI_ADDRFAMILY = Errno(net.EAI_ADDRFAMILY)
|
||||
EAI_AGAIN = Errno(net.EAI_AGAIN)
|
||||
EAI_BADFLAGS = Errno(net.EAI_BADFLAGS)
|
||||
EAI_BADHINTS = Errno(net.EAI_BADHINTS)
|
||||
EAI_FAIL = Errno(net.EAI_FAIL)
|
||||
EAI_FAMILY = Errno(net.EAI_FAMILY)
|
||||
EAI_MEMORY = Errno(net.EAI_MEMORY)
|
||||
EAI_NODATA = Errno(net.EAI_NODATA)
|
||||
EAI_NONAME = Errno(net.EAI_NONAME)
|
||||
EAI_OVERFLOW = Errno(net.EAI_OVERFLOW)
|
||||
EAI_PROTOCOL = Errno(net.EAI_PROTOCOL)
|
||||
EAI_SERVICE = Errno(net.EAI_SERVICE)
|
||||
EAI_SOCKTYPE = Errno(net.EAI_SOCKTYPE)
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
32
internal/lib/os/wait_wait6.go
Normal file
32
internal/lib/os/wait_wait6.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2016 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 dragonfly || freebsd || netbsd
|
||||
|
||||
package os
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// blockUntilWaitable attempts to block until a call to p.Wait will
|
||||
// succeed immediately, and reports whether it has done so.
|
||||
// It does not actually call p.Wait.
|
||||
func (p *Process) blockUntilWaitable() (bool, error) {
|
||||
var errno syscall.Errno
|
||||
for {
|
||||
_, errno = wait6(_P_PID, p.Pid, syscall.WEXITED|syscall.WNOWAIT)
|
||||
if errno != syscall.EINTR {
|
||||
break
|
||||
}
|
||||
}
|
||||
// TODO(xsw):
|
||||
// runtime.KeepAlive(p)
|
||||
if errno == syscall.ENOSYS {
|
||||
return false, nil
|
||||
} else if errno != 0 {
|
||||
return false, NewSyscallError("wait6", errno)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
55
internal/lib/os/wait_waitid.go
Normal file
55
internal/lib/os/wait_waitid.go
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// We used to used this code for Darwin, but according to issue #19314
|
||||
// waitid returns if the process is stopped, even when using WEXITED.
|
||||
|
||||
//go:build linux
|
||||
|
||||
package os
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
const _P_PID = 1
|
||||
|
||||
// int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
|
||||
//
|
||||
//go:linkname waitid C.waitid
|
||||
func waitid(idtype, id uintptr, infop *uint64, options c.Int) c.Int
|
||||
|
||||
// blockUntilWaitable attempts to block until a call to p.Wait will
|
||||
// succeed immediately, and reports whether it has done so.
|
||||
// It does not actually call p.Wait.
|
||||
func (p *Process) blockUntilWaitable() (bool, error) {
|
||||
// The waitid system call expects a pointer to a siginfo_t,
|
||||
// which is 128 bytes on all Linux systems.
|
||||
// On darwin/amd64, it requires 104 bytes.
|
||||
// We don't care about the values it returns.
|
||||
var siginfo [16]uint64
|
||||
psig := &siginfo[0]
|
||||
var e syscall.Errno
|
||||
for {
|
||||
e = syscall.Errno(waitid(_P_PID, uintptr(p.Pid), psig, syscall.WEXITED|syscall.WNOWAIT))
|
||||
if e != syscall.EINTR {
|
||||
break
|
||||
}
|
||||
}
|
||||
// TODO(xsw):
|
||||
// runtime.KeepAlive(p)
|
||||
if e != 0 {
|
||||
// waitid has been available since Linux 2.6.9, but
|
||||
// reportedly is not available in Ubuntu on Windows.
|
||||
// See issue 16610.
|
||||
if e == syscall.ENOSYS {
|
||||
return false, nil
|
||||
}
|
||||
return false, NewSyscallError("waitid", e)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@@ -11,6 +11,8 @@ package syscall
|
||||
import (
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
)
|
||||
|
||||
type SysProcAttr struct {
|
||||
@@ -77,8 +79,8 @@ func init() {
|
||||
// split the stack, or acquire mutexes). We can't call RawSyscall
|
||||
// because it's not safe even for BSD-subsystem calls.
|
||||
//
|
||||
//go:norace
|
||||
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
|
||||
// func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
|
||||
func forkAndExecInChild(argv0 *c.Char, argv, envv **c.Char, chroot, dir *c.Char, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
|
||||
// Declare all variables at top in case any
|
||||
// declarations require heap allocation (e.g., err1).
|
||||
var (
|
||||
|
||||
@@ -52,8 +52,6 @@ func runtime_AfterForkInChild()
|
||||
// For the same reason compiler does not race instrument it.
|
||||
// The calls to rawSyscall are okay because they are assembly
|
||||
// functions that do not grow the stack.
|
||||
//
|
||||
//go:norace
|
||||
func forkAndExecInChild(argv0 *c.Char, argv, envv **c.Char, chroot, dir *c.Char, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err1 Errno) {
|
||||
// Declare all variables at top in case any
|
||||
// declarations require heap allocation (e.g., err1).
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
package syscall
|
||||
|
||||
import "github.com/goplus/llgo/c"
|
||||
|
||||
// Linux unshare/clone/clone2/clone3 flags, architecture-independent,
|
||||
// copied from linux/sched.h.
|
||||
const (
|
||||
@@ -119,8 +121,8 @@ func runtime_AfterForkInChild()
|
||||
// The calls to RawSyscall are okay because they are assembly
|
||||
// functions that do not grow the stack.
|
||||
//
|
||||
//go:norace
|
||||
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
|
||||
// func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
|
||||
func forkAndExecInChild(argv0 *c.Char, argv, envv **c.Char, chroot, dir *c.Char, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
|
||||
/* TODO(xsw):
|
||||
// Set up and fork. This returns immediately in the parent or
|
||||
// if there's an error.
|
||||
|
||||
105
internal/lib/syscall/forkpipe2.go
Normal file
105
internal/lib/syscall/forkpipe2.go
Normal file
@@ -0,0 +1,105 @@
|
||||
// Copyright 2017 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 dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/goplus/llgo/c/syscall"
|
||||
)
|
||||
|
||||
// forkExecPipe atomically opens a pipe with O_CLOEXEC set on both file
|
||||
// descriptors.
|
||||
func forkExecPipe(p []int) error {
|
||||
return Pipe2(p, syscall.O_CLOEXEC)
|
||||
}
|
||||
|
||||
var (
|
||||
// Guard the forking variable.
|
||||
forkingLock sync.Mutex
|
||||
// Number of goroutines currently forking, and thus the
|
||||
// number of goroutines holding a conceptual write lock
|
||||
// on ForkLock.
|
||||
forking int
|
||||
)
|
||||
|
||||
// TODO(xsw):
|
||||
// hasWaitingReaders reports whether any goroutine is waiting
|
||||
// to acquire a read lock on rw. It is defined in the sync package.
|
||||
func hasWaitingReaders(rw *sync.RWMutex) bool {
|
||||
panic("todo: syscall.hasWaitingReaders in sync package")
|
||||
}
|
||||
|
||||
// acquireForkLock acquires a write lock on ForkLock.
|
||||
// ForkLock is exported and we've promised that during a fork
|
||||
// we will call ForkLock.Lock, so that no other threads create
|
||||
// new fds that are not yet close-on-exec before we fork.
|
||||
// But that forces all fork calls to be serialized, which is bad.
|
||||
// But we haven't promised that serialization, and it is essentially
|
||||
// undetectable by other users of ForkLock, which is good.
|
||||
// Avoid the serialization by ensuring that ForkLock is locked
|
||||
// at the first fork and unlocked when there are no more forks.
|
||||
func acquireForkLock() {
|
||||
forkingLock.Lock()
|
||||
defer forkingLock.Unlock()
|
||||
|
||||
if forking == 0 {
|
||||
// There is no current write lock on ForkLock.
|
||||
ForkLock.Lock()
|
||||
forking++
|
||||
return
|
||||
}
|
||||
|
||||
// ForkLock is currently locked for writing.
|
||||
|
||||
if hasWaitingReaders(&ForkLock) {
|
||||
// ForkLock is locked for writing, and at least one
|
||||
// goroutine is waiting to read from it.
|
||||
// To avoid lock starvation, allow readers to proceed.
|
||||
// The simple way to do this is for us to acquire a
|
||||
// read lock. That will block us until all current
|
||||
// conceptual write locks are released.
|
||||
//
|
||||
// Note that this case is unusual on modern systems
|
||||
// with O_CLOEXEC and SOCK_CLOEXEC. On those systems
|
||||
// the standard library should never take a read
|
||||
// lock on ForkLock.
|
||||
|
||||
forkingLock.Unlock()
|
||||
|
||||
ForkLock.RLock()
|
||||
ForkLock.RUnlock()
|
||||
|
||||
forkingLock.Lock()
|
||||
|
||||
// Readers got a chance, so now take the write lock.
|
||||
|
||||
if forking == 0 {
|
||||
ForkLock.Lock()
|
||||
}
|
||||
}
|
||||
|
||||
forking++
|
||||
}
|
||||
|
||||
// releaseForkLock releases the conceptual write lock on ForkLock
|
||||
// acquired by acquireForkLock.
|
||||
func releaseForkLock() {
|
||||
forkingLock.Lock()
|
||||
defer forkingLock.Unlock()
|
||||
|
||||
if forking <= 0 {
|
||||
panic("syscall.releaseForkLock: negative count")
|
||||
}
|
||||
|
||||
forking--
|
||||
|
||||
if forking == 0 {
|
||||
// No more conceptual write locks.
|
||||
ForkLock.Unlock()
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,108 @@
|
||||
|
||||
package syscall
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/syscall"
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
type WaitStatus uint32
|
||||
|
||||
// Wait status is 7 bits at bottom, either 0 (exited),
|
||||
// 0x7F (stopped), or a signal number that caused an exit.
|
||||
// The 0x80 bit is whether there was a core dump.
|
||||
// An extra number (exit code, signal causing a stop)
|
||||
// is in the high bits. At least that's the idea.
|
||||
// There are various irregularities. For example, the
|
||||
// "continued" status is 0xFFFF, distinguishing itself
|
||||
// from stopped via the core dump bit.
|
||||
|
||||
const (
|
||||
mask = 0x7F
|
||||
core = 0x80
|
||||
exited = 0x00
|
||||
stopped = 0x7F
|
||||
shift = 8
|
||||
)
|
||||
|
||||
func (w WaitStatus) Exited() bool { return w&mask == exited }
|
||||
|
||||
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited }
|
||||
|
||||
func (w WaitStatus) Stopped() bool { return w&0xFF == stopped }
|
||||
|
||||
func (w WaitStatus) Continued() bool { return w == 0xFFFF }
|
||||
|
||||
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
|
||||
|
||||
func (w WaitStatus) ExitStatus() int {
|
||||
if !w.Exited() {
|
||||
return -1
|
||||
}
|
||||
return int(w>>shift) & 0xFF
|
||||
}
|
||||
|
||||
func (w WaitStatus) Signal() Signal {
|
||||
if !w.Signaled() {
|
||||
return -1
|
||||
}
|
||||
return Signal(w & mask)
|
||||
}
|
||||
|
||||
func (w WaitStatus) StopSignal() Signal {
|
||||
if !w.Stopped() {
|
||||
return -1
|
||||
}
|
||||
return Signal(w>>shift) & 0xFF
|
||||
}
|
||||
|
||||
/* TODO(xsw):
|
||||
func (w WaitStatus) TrapCause() int {
|
||||
if w.StopSignal() != SIGTRAP {
|
||||
return -1
|
||||
}
|
||||
return int(w>>shift) >> 8
|
||||
}
|
||||
*/
|
||||
|
||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *syscall.Rusage) (wpid int, err error) {
|
||||
var status c.Int
|
||||
wpid, err = wait4(pid, &status, options, rusage)
|
||||
if wstatus != nil {
|
||||
*wstatus = WaitStatus(status)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// int pipe2(int pipefd[2], int flags);
|
||||
//
|
||||
//go:linkname pipe2 C.pipe2
|
||||
func pipe2(pipefd *[2]c.Int, flags c.Int) c.Int
|
||||
|
||||
func Pipe2(p []int, flags int) error {
|
||||
if len(p) != 2 {
|
||||
return Errno(syscall.EINVAL)
|
||||
}
|
||||
var pp [2]c.Int
|
||||
ret := pipe2(&pp, c.Int(flags))
|
||||
if ret == 0 {
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return nil
|
||||
}
|
||||
return Errno(ret)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||
panic("todo: syscall.Faccessat")
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user