mirror of
https://github.com/criyle/go-sandbox.git
synced 2025-11-04 14:49:53 +08:00
update mounts
This commit is contained in:
parent
a4c78dcf5d
commit
a24933ac82
@ -218,6 +218,8 @@ func start() (*types.Result, error) {
|
|||||||
FileSize: outputLimit << 20,
|
FileSize: outputLimit << 20,
|
||||||
Stack: stackLimit << 20,
|
Stack: stackLimit << 20,
|
||||||
}
|
}
|
||||||
|
debug("rlimit: ", rlims)
|
||||||
|
debug("defaultMount: ", mount.DefaultMounts)
|
||||||
|
|
||||||
actionDefault := seccomp.ActionKill
|
actionDefault := seccomp.ActionKill
|
||||||
if showDetails {
|
if showDetails {
|
||||||
@ -274,7 +276,7 @@ func start() (*types.Result, error) {
|
|||||||
return nil, fmt.Errorf("cannot make temp root for new namespace")
|
return nil, fmt.Errorf("cannot make temp root for new namespace")
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(root)
|
defer os.RemoveAll(root)
|
||||||
mounts, err := mount.NewBuilder().WithMounts(unshare.DefaultMounts).WithBind(root, "w", true).Build(true)
|
mounts, err := mount.NewBuilder().WithMounts(mount.DefaultMounts).WithBind(root, "w", true).Build(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot make rootfs mounts")
|
return nil, fmt.Errorf("cannot make rootfs mounts")
|
||||||
}
|
}
|
||||||
@ -374,6 +376,7 @@ func debug(v ...interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Status defines uoj/run_program constants
|
||||||
type Status int
|
type Status int
|
||||||
|
|
||||||
// UOJ run_program constants
|
// UOJ run_program constants
|
||||||
|
|||||||
@ -1,55 +0,0 @@
|
|||||||
package daemon
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/criyle/go-sandbox/pkg/mount"
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
roBind = unix.MS_BIND | unix.MS_NOSUID | unix.MS_PRIVATE | unix.MS_RDONLY
|
|
||||||
mFlag = unix.MS_NOSUID | unix.MS_NOATIME | unix.MS_NODEV
|
|
||||||
)
|
|
||||||
|
|
||||||
// default parameters. I was tend to reuse the configs but it is hard since there are some
|
|
||||||
// cross device symbolic
|
|
||||||
var (
|
|
||||||
DefaultPath = "PATH=/usr/local/bin:/usr/bin:/bin"
|
|
||||||
|
|
||||||
// rootfs created by bind mounting
|
|
||||||
DefaultMounts = []mount.Mount{
|
|
||||||
{
|
|
||||||
Source: "/usr",
|
|
||||||
Target: "usr",
|
|
||||||
Flags: roBind,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Source: "/lib",
|
|
||||||
Target: "lib",
|
|
||||||
Flags: roBind,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Source: "/lib64",
|
|
||||||
Target: "lib64",
|
|
||||||
Flags: roBind,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Source: "/bin",
|
|
||||||
Target: "bin",
|
|
||||||
Flags: roBind,
|
|
||||||
},
|
|
||||||
// work dir at /w
|
|
||||||
{
|
|
||||||
Source: "tmpfs",
|
|
||||||
Target: "w",
|
|
||||||
FsType: "tmpfs",
|
|
||||||
Flags: mFlag,
|
|
||||||
},
|
|
||||||
// tmpfs at /tmp
|
|
||||||
{
|
|
||||||
Source: "tmpfs",
|
|
||||||
Target: "tmp",
|
|
||||||
FsType: "tmpfs",
|
|
||||||
Flags: mFlag,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@ -13,6 +13,9 @@ import (
|
|||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DefaultPath defines path evironment variable for container init process
|
||||||
|
const DefaultPath = "PATH=/usr/local/bin:/usr/bin:/bin"
|
||||||
|
|
||||||
// Builder builds instance of container masters
|
// Builder builds instance of container masters
|
||||||
type Builder struct {
|
type Builder struct {
|
||||||
// Root is container root mount path, empty uses current work path
|
// Root is container root mount path, empty uses current work path
|
||||||
@ -56,7 +59,11 @@ func (b *Builder) Build() (*Master, error) {
|
|||||||
// container mount points
|
// container mount points
|
||||||
mounts := b.Mounts
|
mounts := b.Mounts
|
||||||
if len(mounts) == 0 {
|
if len(mounts) == 0 {
|
||||||
if mounts, err = mount.NewBuilder().WithMounts(DefaultMounts).Build(true); err != nil {
|
if mounts, err = mount.NewBuilder().
|
||||||
|
WithMounts(mount.DefaultMounts).
|
||||||
|
WithTmpfs("w", ""). // work dir
|
||||||
|
WithTmpfs("tmp", ""). // tmp
|
||||||
|
Build(true); err != nil {
|
||||||
return nil, fmt.Errorf("daemon: failed to build rootfs mount %v", err)
|
return nil, fmt.Errorf("daemon: failed to build rootfs mount %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
34
pkg/mount/default.go
Normal file
34
pkg/mount/default.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package mount
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
// RoBind is read-only bind mount flags
|
||||||
|
const (
|
||||||
|
RoBind = unix.MS_BIND | unix.MS_NOSUID | unix.MS_PRIVATE | unix.MS_RDONLY
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DefaultMounts is a example of minimal rootfs
|
||||||
|
DefaultMounts = []Mount{
|
||||||
|
{
|
||||||
|
Source: "/usr",
|
||||||
|
Target: "usr",
|
||||||
|
Flags: RoBind,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Source: "/lib",
|
||||||
|
Target: "lib",
|
||||||
|
Flags: RoBind,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Source: "/lib64",
|
||||||
|
Target: "lib64",
|
||||||
|
Flags: RoBind,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Source: "/bin",
|
||||||
|
Target: "bin",
|
||||||
|
Flags: RoBind,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
@ -26,9 +26,9 @@ func (m *Mount) Mount() error {
|
|||||||
|
|
||||||
func (m Mount) String() string {
|
func (m Mount) String() string {
|
||||||
switch {
|
switch {
|
||||||
case m.Flags|syscall.MS_BIND == syscall.MS_BIND:
|
case m.Flags&syscall.MS_BIND == syscall.MS_BIND:
|
||||||
flag := "rw"
|
flag := "rw"
|
||||||
if m.Flags|syscall.MS_RDONLY == syscall.MS_RDONLY {
|
if m.Flags&syscall.MS_RDONLY == syscall.MS_RDONLY {
|
||||||
flag = "ro"
|
flag = "ro"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("bind[%s:%s:%s]", m.Source, m.Target, flag)
|
return fmt.Sprintf("bind[%s:%s:%s]", m.Source, m.Target, flag)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package ptracer
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -14,31 +15,19 @@ import (
|
|||||||
// Trace starts new goroutine and trace runner with ptrace
|
// Trace starts new goroutine and trace runner with ptrace
|
||||||
func (t *Tracer) Trace(c context.Context) <-chan types.Result {
|
func (t *Tracer) Trace(c context.Context) <-chan types.Result {
|
||||||
result := make(chan types.Result, 1)
|
result := make(chan types.Result, 1)
|
||||||
start := make(chan struct{})
|
|
||||||
finish := make(chan struct{})
|
|
||||||
|
|
||||||
// run
|
|
||||||
go func() {
|
go func() {
|
||||||
defer close(finish)
|
result <- t.TraceRun(c)
|
||||||
ret, err := t.TraceRun(c.Done(), start)
|
|
||||||
ret.Error = err.Error()
|
|
||||||
result <- ret
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
select {
|
|
||||||
case <-start:
|
|
||||||
case <-finish:
|
|
||||||
}
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// TraceRun start and traces all child process by runner in the calling goroutine
|
// TraceRun start and traces all child process by runner in the calling goroutine
|
||||||
// parameter done used to cancel work, start is used notify child starts
|
// parameter done used to cancel work, start is used notify child starts
|
||||||
func (t *Tracer) TraceRun(done <-chan struct{}, start chan<- struct{}) (result types.Result, err error) {
|
func (t *Tracer) TraceRun(c context.Context) (result types.Result) {
|
||||||
var (
|
var (
|
||||||
|
status = types.StatusNormal
|
||||||
wstatus unix.WaitStatus // wait4 wait status
|
wstatus unix.WaitStatus // wait4 wait status
|
||||||
rusage unix.Rusage // wait4 rusage
|
rusage unix.Rusage // wait4 rusage
|
||||||
tle bool // whether the timmer triggered due to timeout
|
|
||||||
traced = make(map[int]bool) // store all process that have set ptrace options
|
traced = make(map[int]bool) // store all process that have set ptrace options
|
||||||
execved = false // store whether the runner process have successfully execvd
|
execved = false // store whether the runner process have successfully execvd
|
||||||
pid int // store pid of wait4 result
|
pid int // store pid of wait4 result
|
||||||
@ -56,32 +45,26 @@ func (t *Tracer) TraceRun(done <-chan struct{}, start chan<- struct{}) (result t
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Handler.Debug("start tracee failed: ", err)
|
t.Handler.Debug("start tracee failed: ", err)
|
||||||
result.Status = types.StatusRunnerError
|
result.Status = types.StatusRunnerError
|
||||||
return result, err
|
result.Error = err.Error()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
close(start)
|
cc, cancel := context.WithCancel(c)
|
||||||
finish := make(chan struct{})
|
defer cancel()
|
||||||
defer close(finish)
|
|
||||||
|
|
||||||
// handle cancelation
|
// handle cancelation
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
<-cc.Done()
|
||||||
case <-done:
|
killAll(pgid)
|
||||||
tle = true
|
|
||||||
killAll(pgid)
|
|
||||||
case <-finish:
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// handler potential panic and tle
|
// handler potential panic and tle
|
||||||
// also ensure processes was well terminated
|
// also ensure processes was well terminated
|
||||||
defer func() {
|
defer func() {
|
||||||
if tle {
|
if err := recover(); err != nil {
|
||||||
err = types.StatusTimeLimitExceeded
|
t.Handler.Debug("panic: ", err)
|
||||||
}
|
result.Status = types.StatusRunnerError
|
||||||
if err2 := recover(); err2 != nil {
|
result.Error = fmt.Sprintf("%v", err)
|
||||||
t.Handler.Debug(err2)
|
|
||||||
err = types.StatusRunnerError
|
|
||||||
}
|
}
|
||||||
// kill all tracee upon return
|
// kill all tracee upon return
|
||||||
killAll(pgid)
|
killAll(pgid)
|
||||||
@ -90,7 +73,7 @@ func (t *Tracer) TraceRun(done <-chan struct{}, start chan<- struct{}) (result t
|
|||||||
result.RunningTime = time.Since(fTime)
|
result.RunningTime = time.Since(fTime)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// trace unixs
|
// ptrace pool loop
|
||||||
for {
|
for {
|
||||||
if execved {
|
if execved {
|
||||||
// Wait for all child in the process group
|
// Wait for all child in the process group
|
||||||
@ -101,11 +84,12 @@ func (t *Tracer) TraceRun(done <-chan struct{}, start chan<- struct{}) (result t
|
|||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Handler.Debug("wait4 failed: ", err)
|
t.Handler.Debug("wait4 failed: ", err)
|
||||||
return result, types.StatusRunnerError
|
result.Status = types.StatusRunnerError
|
||||||
|
result.Error = err.Error()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
t.Handler.Debug("------ ", pid, " ------")
|
t.Handler.Debug("------ ", pid, " ------")
|
||||||
|
|
||||||
status := types.StatusNormal
|
|
||||||
if pid == pgid {
|
if pid == pgid {
|
||||||
// update resource usage and check against limits
|
// update resource usage and check against limits
|
||||||
userTime := time.Duration(rusage.Utime.Nano()) // ns
|
userTime := time.Duration(rusage.Utime.Nano()) // ns
|
||||||
@ -124,7 +108,7 @@ func (t *Tracer) TraceRun(done <-chan struct{}, start chan<- struct{}) (result t
|
|||||||
Memory: userMem,
|
Memory: userMem,
|
||||||
}
|
}
|
||||||
if status != types.StatusNormal {
|
if status != types.StatusNormal {
|
||||||
return result, status
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,10 +120,16 @@ func (t *Tracer) TraceRun(done <-chan struct{}, start chan<- struct{}) (result t
|
|||||||
if pid == pgid {
|
if pid == pgid {
|
||||||
if execved {
|
if execved {
|
||||||
result.ExitStatus = wstatus.ExitStatus()
|
result.ExitStatus = wstatus.ExitStatus()
|
||||||
return result, nil
|
if result.ExitStatus == 0 {
|
||||||
|
result.Status = types.StatusNormal
|
||||||
|
} else {
|
||||||
|
result.Status = types.StatusNonzeroExitStatus
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
result.Status = types.StatusRunnerError
|
result.Status = types.StatusRunnerError
|
||||||
return result, types.StatusRunnerError
|
result.Error = "child process exit before execve"
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
case wstatus.Signaled():
|
case wstatus.Signaled():
|
||||||
@ -159,20 +149,21 @@ func (t *Tracer) TraceRun(done <-chan struct{}, start chan<- struct{}) (result t
|
|||||||
}
|
}
|
||||||
result.Status = status
|
result.Status = status
|
||||||
result.ExitStatus = int(sig)
|
result.ExitStatus = int(sig)
|
||||||
return result, status
|
return
|
||||||
}
|
}
|
||||||
unix.PtraceCont(pid, int(sig))
|
unix.PtraceCont(pid, int(sig))
|
||||||
|
|
||||||
case wstatus.Stopped():
|
case wstatus.Stopped():
|
||||||
// Set option if the process is newly forked
|
// Set option if the process is newly forked
|
||||||
if !traced[pid] {
|
if !traced[pid] {
|
||||||
t.Handler.Debug("set ptrace option")
|
t.Handler.Debug("set ptrace option for", pid)
|
||||||
traced[pid] = true
|
traced[pid] = true
|
||||||
// Ptrace set option valid if the tracee is stopped
|
// Ptrace set option valid if the tracee is stopped
|
||||||
err = setPtraceOption(pid)
|
err = setPtraceOption(pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result.Status = types.StatusRunnerError
|
result.Status = types.StatusRunnerError
|
||||||
return result, err
|
result.Error = err.Error()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +176,8 @@ func (t *Tracer) TraceRun(done <-chan struct{}, start chan<- struct{}) (result t
|
|||||||
err := t.handleTrap(pid)
|
err := t.handleTrap(pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result.Status = types.StatusDisallowedSyscall
|
result.Status = types.StatusDisallowedSyscall
|
||||||
return result, err
|
result.Error = err.Error()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
t.Handler.Debug("ptrace seccomp before execve (should be the execve syscall)")
|
t.Handler.Debug("ptrace seccomp before execve (should be the execve syscall)")
|
||||||
@ -219,7 +211,7 @@ func (t *Tracer) TraceRun(done <-chan struct{}, start chan<- struct{}) (result t
|
|||||||
}
|
}
|
||||||
if status != types.StatusNormal {
|
if status != types.StatusNormal {
|
||||||
result.Status = status
|
result.Status = status
|
||||||
return result, status
|
return
|
||||||
}
|
}
|
||||||
// Likely encountered SIGSEGV (segment violation)
|
// Likely encountered SIGSEGV (segment violation)
|
||||||
// Or compiler child exited
|
// Or compiler child exited
|
||||||
|
|||||||
@ -1,37 +0,0 @@
|
|||||||
// +build linux
|
|
||||||
|
|
||||||
package unshare
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
"github.com/criyle/go-sandbox/pkg/mount"
|
|
||||||
)
|
|
||||||
|
|
||||||
const roBind = unix.MS_BIND | unix.MS_NOSUID | unix.MS_PRIVATE | unix.MS_RDONLY
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultMounts is a example of minimal rootfs
|
|
||||||
DefaultMounts = []mount.Mount{
|
|
||||||
{
|
|
||||||
Source: "/usr",
|
|
||||||
Target: "usr",
|
|
||||||
Flags: roBind,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Source: "/lib",
|
|
||||||
Target: "lib",
|
|
||||||
Flags: roBind,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Source: "/lib64",
|
|
||||||
Target: "lib64",
|
|
||||||
Flags: roBind,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Source: "/bin",
|
|
||||||
Target: "bin",
|
|
||||||
Flags: roBind,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@ -40,31 +40,18 @@ func (r *Runner) Run(c context.Context) <-chan types.Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result := make(chan types.Result, 1)
|
result := make(chan types.Result, 1)
|
||||||
start := make(chan struct{})
|
|
||||||
finish := make(chan struct{})
|
|
||||||
|
|
||||||
// run
|
|
||||||
go func() {
|
go func() {
|
||||||
defer close(finish)
|
result <- r.trace(c, ch)
|
||||||
ret, err2 := r.Trace(c.Done(), start, ch)
|
|
||||||
ret.Error = err2.Error()
|
|
||||||
result <- ret
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
select {
|
|
||||||
case <-start:
|
|
||||||
case <-finish:
|
|
||||||
}
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trace tracks child processes
|
// Trace tracks child processes
|
||||||
func (r *Runner) Trace(done <-chan struct{}, start chan<- struct{},
|
func (r *Runner) trace(c context.Context, runner *forkexec.Runner) (result types.Result) {
|
||||||
runner *forkexec.Runner) (result types.Result, err error) {
|
|
||||||
var (
|
var (
|
||||||
wstatus unix.WaitStatus // wait4 wait status
|
wstatus unix.WaitStatus // wait4 wait status
|
||||||
rusage unix.Rusage // wait4 rusage
|
rusage unix.Rusage // wait4 rusage
|
||||||
tle = false
|
|
||||||
status = types.StatusNormal
|
status = types.StatusNormal
|
||||||
sTime = time.Now() // start time
|
sTime = time.Now() // start time
|
||||||
fTime time.Time // finish time for setup
|
fTime time.Time // finish time for setup
|
||||||
@ -75,28 +62,21 @@ func (r *Runner) Trace(done <-chan struct{}, start chan<- struct{},
|
|||||||
r.println("Starts: ", pgid, err)
|
r.println("Starts: ", pgid, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result.Status = types.StatusRunnerError
|
result.Status = types.StatusRunnerError
|
||||||
return result, err
|
result.Error = err.Error()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
close(start)
|
cc, cancel := context.WithCancel(c)
|
||||||
finish := make(chan struct{})
|
defer cancel()
|
||||||
defer close(finish)
|
|
||||||
|
|
||||||
// handle cancel
|
// handle cancel
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
<-cc.Done()
|
||||||
case <-done:
|
killAll(pgid)
|
||||||
tle = true
|
|
||||||
killAll(pgid)
|
|
||||||
case <-finish:
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// kill all tracee upon return
|
||||||
defer func() {
|
defer func() {
|
||||||
if tle {
|
|
||||||
err = types.StatusTimeLimitExceeded
|
|
||||||
}
|
|
||||||
// kill all tracee upon return
|
|
||||||
killAll(pgid)
|
killAll(pgid)
|
||||||
collectZombie(pgid)
|
collectZombie(pgid)
|
||||||
result.SetUpTime = fTime.Sub(sTime)
|
result.SetUpTime = fTime.Sub(sTime)
|
||||||
@ -104,17 +84,18 @@ func (r *Runner) Trace(done <-chan struct{}, start chan<- struct{},
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
fTime = time.Now()
|
fTime = time.Now()
|
||||||
loop:
|
|
||||||
for {
|
for {
|
||||||
_, err := unix.Wait4(pgid, &wstatus, 0, &rusage)
|
_, err := unix.Wait4(pgid, &wstatus, 0, &rusage)
|
||||||
r.println("wait4: ", wstatus)
|
r.println("wait4: ", wstatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, types.StatusRunnerError
|
result.Status = types.StatusRunnerError
|
||||||
|
result.Error = err.Error()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// update resource usage and check against limits
|
// update resource usage and check against limits
|
||||||
userTime := time.Duration(rusage.Utime.Nano()) // ns
|
userTime := time.Duration(rusage.Utime.Nano()) // ns
|
||||||
userMem := types.Size(rusage.Maxrss << 10) // bytes // kb
|
userMem := types.Size(rusage.Maxrss << 10) // bytes
|
||||||
|
|
||||||
// check tle / mle
|
// check tle / mle
|
||||||
if userTime > r.Limit.TimeLimit {
|
if userTime > r.Limit.TimeLimit {
|
||||||
@ -129,13 +110,15 @@ loop:
|
|||||||
Memory: userMem,
|
Memory: userMem,
|
||||||
}
|
}
|
||||||
if status != types.StatusNormal {
|
if status != types.StatusNormal {
|
||||||
return result, status
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case wstatus.Exited():
|
case wstatus.Exited():
|
||||||
|
result.Status = types.StatusNormal
|
||||||
result.ExitStatus = wstatus.ExitStatus()
|
result.ExitStatus = wstatus.ExitStatus()
|
||||||
return result, nil
|
return
|
||||||
|
|
||||||
case wstatus.Signaled():
|
case wstatus.Signaled():
|
||||||
sig := wstatus.Signal()
|
sig := wstatus.Signal()
|
||||||
switch sig {
|
switch sig {
|
||||||
@ -150,10 +133,9 @@ loop:
|
|||||||
}
|
}
|
||||||
result.Status = status
|
result.Status = status
|
||||||
result.ExitStatus = int(sig)
|
result.ExitStatus = int(sig)
|
||||||
break loop
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result, status
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// kill all tracee according to pids
|
// kill all tracee according to pids
|
||||||
@ -164,7 +146,6 @@ func killAll(pgid int) {
|
|||||||
// collect died child processes
|
// collect died child processes
|
||||||
func collectZombie(pgid int) {
|
func collectZombie(pgid int) {
|
||||||
var wstatus unix.WaitStatus
|
var wstatus unix.WaitStatus
|
||||||
// collect zombies
|
|
||||||
for {
|
for {
|
||||||
if _, err := unix.Wait4(-pgid, &wstatus, unix.WALL|unix.WNOHANG, nil); err != nil {
|
if _, err := unix.Wait4(-pgid, &wstatus, unix.WALL|unix.WNOHANG, nil); err != nil {
|
||||||
break
|
break
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user