mirror of
https://github.com/criyle/go-sandbox.git
synced 2025-11-04 14:49:53 +08:00
add extra sync for execve
This commit is contained in:
parent
8bf0411dbb
commit
eb93d92b9e
@ -185,8 +185,16 @@ func main() {
|
||||
if err != nil {
|
||||
panic(fmt.Sprintln("failed to execve", err))
|
||||
}
|
||||
println(<-s.Wait)
|
||||
s.Kill <- 1
|
||||
tC := time.After(time.Duration(int64(realTimeLimit) * int64(time.Second)))
|
||||
select {
|
||||
case <-tC:
|
||||
s.Kill <- 1
|
||||
rt = <-s.Wait
|
||||
|
||||
case rt = <-s.Wait:
|
||||
s.Kill <- 1
|
||||
}
|
||||
println(rt)
|
||||
eTime := time.Now()
|
||||
rt.SetUpTime = int64(rTime.Sub(sTime))
|
||||
rt.RunningTime = int64(eTime.Sub(rTime))
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/criyle/go-judger/forkexec"
|
||||
"github.com/criyle/go-judger/types/specs"
|
||||
"github.com/criyle/go-judger/unixsocket"
|
||||
)
|
||||
|
||||
@ -77,17 +78,15 @@ func handleExecve(s *unixsocket.Socket, cmd *Cmd, msg *unixsocket.Msg) error {
|
||||
},
|
||||
}
|
||||
if err2 := sendReply(s, &Reply{}, &msg2); err2 != nil {
|
||||
_ = err2
|
||||
return fmt.Errorf("syncFunc: sendReply(%v)", err2)
|
||||
}
|
||||
cmd2, _, err2 := recvCmd(s)
|
||||
if err2 != nil {
|
||||
_ = err2
|
||||
return fmt.Errorf("syncFunc: recvCmd(%v)", err2)
|
||||
}
|
||||
switch cmd2.Cmd {
|
||||
case cmdKill:
|
||||
return fmt.Errorf("kill")
|
||||
case cmdOk:
|
||||
return nil
|
||||
return fmt.Errorf("syncFunc: recved kill")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -103,37 +102,68 @@ func handleExecve(s *unixsocket.Socket, cmd *Cmd, msg *unixsocket.Msg) error {
|
||||
}
|
||||
pid, err := r.Start()
|
||||
if err != nil {
|
||||
_ = err
|
||||
reply := Reply{Error: fmt.Sprintf("execve: %v", err)}
|
||||
sendReply(s, &reply, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
done := make(chan int)
|
||||
// recv kill
|
||||
go func() {
|
||||
// msg must be kill
|
||||
if _, _, err3 := recvCmd(s); err3 != nil {
|
||||
_ = err3
|
||||
}
|
||||
recvCmd(s)
|
||||
// kill all
|
||||
syscall.Kill(-1, syscall.SIGKILL)
|
||||
// collect zombies
|
||||
for {
|
||||
_, err = syscall.Wait4(-1, nil, 0, nil)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
// signal done
|
||||
close(done)
|
||||
}()
|
||||
var wstatus syscall.WaitStatus
|
||||
|
||||
// wait pid
|
||||
var wstatus syscall.WaitStatus
|
||||
loop:
|
||||
for {
|
||||
_, err = syscall.Wait4(pid, &wstatus, 0, nil)
|
||||
if err != nil {
|
||||
_ = err
|
||||
reply := Reply{Error: fmt.Sprintf("execve: wait4 %v", err)}
|
||||
sendReply(s, &reply, nil)
|
||||
break loop
|
||||
}
|
||||
switch {
|
||||
case wstatus.Exited():
|
||||
reply := Reply{
|
||||
Status: wstatus.ExitStatus(),
|
||||
}
|
||||
if err = sendReply(s, &reply, nil); err != nil {
|
||||
_ = err
|
||||
reply := Reply{ExitStatus: wstatus.ExitStatus()}
|
||||
sendReply(s, &reply, nil)
|
||||
break loop
|
||||
|
||||
case wstatus.Signaled():
|
||||
var status specs.TraceCode
|
||||
switch wstatus.Signal() {
|
||||
// kill signal treats as TLE
|
||||
case syscall.SIGKILL:
|
||||
status = specs.TraceCodeTLE
|
||||
case syscall.SIGXCPU:
|
||||
status = specs.TraceCodeTLE
|
||||
case syscall.SIGXFSZ:
|
||||
status = specs.TraceCodeOLE
|
||||
case syscall.SIGSYS:
|
||||
status = specs.TraceCodeBan
|
||||
default:
|
||||
status = specs.TraceCodeRE
|
||||
}
|
||||
reply := Reply{TraceStatus: status}
|
||||
sendReply(s, &reply, nil)
|
||||
break loop
|
||||
}
|
||||
}
|
||||
return nil
|
||||
// wait for kill msg and reply done for finish
|
||||
<-done
|
||||
return sendReply(s, &Reply{}, nil)
|
||||
}
|
||||
|
||||
func recvCmd(s *unixsocket.Socket) (*Cmd, *unixsocket.Msg, error) {
|
||||
|
||||
@ -34,6 +34,7 @@ Any socket related error will cause the deamon exit (with all process inside con
|
||||
|
||||
import (
|
||||
"github.com/criyle/go-judger/types/rlimit"
|
||||
"github.com/criyle/go-judger/types/specs"
|
||||
)
|
||||
|
||||
// Cmd is the control message send into deamon
|
||||
@ -49,6 +50,7 @@ type Cmd struct {
|
||||
|
||||
// Reply is the reply message send back to controller
|
||||
type Reply struct {
|
||||
Error string // empty if no error
|
||||
Status int // waitpid exit status
|
||||
Error string // empty if no error
|
||||
ExitStatus int // waitpid exit status
|
||||
TraceStatus specs.TraceCode // TraceCode
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/criyle/go-judger/types/rlimit"
|
||||
"github.com/criyle/go-judger/types/specs"
|
||||
"github.com/criyle/go-judger/unixsocket"
|
||||
)
|
||||
|
||||
@ -22,7 +23,7 @@ type ExecveParam struct {
|
||||
// Wait channel will produce the waitpid exit status
|
||||
// Kill channel will kill the process if value received
|
||||
type ExecveStatus struct {
|
||||
Wait <-chan int
|
||||
Wait <-chan specs.TraceResult
|
||||
Kill chan<- int
|
||||
}
|
||||
|
||||
@ -55,23 +56,23 @@ func (m *Master) Execve(param *ExecveParam) (*ExecveStatus, error) {
|
||||
if err := m.sendCmd(&Cmd{Cmd: cmdOk}, nil); err != nil {
|
||||
return nil, fmt.Errorf("execve: ok failed(%v)", err)
|
||||
}
|
||||
wait := make(chan int)
|
||||
wait := make(chan specs.TraceResult)
|
||||
kill := make(chan int)
|
||||
// Wait
|
||||
go func() {
|
||||
reply2, _, err2 := m.recvReply()
|
||||
if err2 != nil {
|
||||
_ = err2
|
||||
reply2, _, _ := m.recvReply()
|
||||
wait <- specs.TraceResult{
|
||||
ExitCode: reply2.ExitStatus,
|
||||
TraceStatus: reply2.TraceStatus,
|
||||
}
|
||||
wait <- reply2.Status
|
||||
// done signal (should recv after kill)
|
||||
m.recvReply()
|
||||
close(wait)
|
||||
}()
|
||||
// Kill
|
||||
go func() {
|
||||
<-kill
|
||||
err3 := m.sendCmd(&Cmd{Cmd: cmdKill}, nil)
|
||||
if err3 != nil {
|
||||
_ = err3
|
||||
}
|
||||
m.sendCmd(&Cmd{Cmd: cmdKill}, nil)
|
||||
}()
|
||||
return &ExecveStatus{
|
||||
Wait: wait,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user