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 {
|
if err != nil {
|
||||||
panic(fmt.Sprintln("failed to execve", err))
|
panic(fmt.Sprintln("failed to execve", err))
|
||||||
}
|
}
|
||||||
println(<-s.Wait)
|
tC := time.After(time.Duration(int64(realTimeLimit) * int64(time.Second)))
|
||||||
s.Kill <- 1
|
select {
|
||||||
|
case <-tC:
|
||||||
|
s.Kill <- 1
|
||||||
|
rt = <-s.Wait
|
||||||
|
|
||||||
|
case rt = <-s.Wait:
|
||||||
|
s.Kill <- 1
|
||||||
|
}
|
||||||
|
println(rt)
|
||||||
eTime := time.Now()
|
eTime := time.Now()
|
||||||
rt.SetUpTime = int64(rTime.Sub(sTime))
|
rt.SetUpTime = int64(rTime.Sub(sTime))
|
||||||
rt.RunningTime = int64(eTime.Sub(rTime))
|
rt.RunningTime = int64(eTime.Sub(rTime))
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/criyle/go-judger/forkexec"
|
"github.com/criyle/go-judger/forkexec"
|
||||||
|
"github.com/criyle/go-judger/types/specs"
|
||||||
"github.com/criyle/go-judger/unixsocket"
|
"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 {
|
if err2 := sendReply(s, &Reply{}, &msg2); err2 != nil {
|
||||||
_ = err2
|
return fmt.Errorf("syncFunc: sendReply(%v)", err2)
|
||||||
}
|
}
|
||||||
cmd2, _, err2 := recvCmd(s)
|
cmd2, _, err2 := recvCmd(s)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
_ = err2
|
return fmt.Errorf("syncFunc: recvCmd(%v)", err2)
|
||||||
}
|
}
|
||||||
switch cmd2.Cmd {
|
switch cmd2.Cmd {
|
||||||
case cmdKill:
|
case cmdKill:
|
||||||
return fmt.Errorf("kill")
|
return fmt.Errorf("syncFunc: recved kill")
|
||||||
case cmdOk:
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -103,37 +102,68 @@ func handleExecve(s *unixsocket.Socket, cmd *Cmd, msg *unixsocket.Msg) error {
|
|||||||
}
|
}
|
||||||
pid, err := r.Start()
|
pid, err := r.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = err
|
reply := Reply{Error: fmt.Sprintf("execve: %v", err)}
|
||||||
|
sendReply(s, &reply, nil)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done := make(chan int)
|
||||||
// recv kill
|
// recv kill
|
||||||
go func() {
|
go func() {
|
||||||
// msg must be kill
|
// msg must be kill
|
||||||
if _, _, err3 := recvCmd(s); err3 != nil {
|
recvCmd(s)
|
||||||
_ = err3
|
|
||||||
}
|
|
||||||
// kill all
|
// kill all
|
||||||
syscall.Kill(-1, syscall.SIGKILL)
|
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
|
// wait pid
|
||||||
|
var wstatus syscall.WaitStatus
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
_, err = syscall.Wait4(pid, &wstatus, 0, nil)
|
_, err = syscall.Wait4(pid, &wstatus, 0, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = err
|
reply := Reply{Error: fmt.Sprintf("execve: wait4 %v", err)}
|
||||||
|
sendReply(s, &reply, nil)
|
||||||
|
break loop
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case wstatus.Exited():
|
case wstatus.Exited():
|
||||||
reply := Reply{
|
reply := Reply{ExitStatus: wstatus.ExitStatus()}
|
||||||
Status: wstatus.ExitStatus(),
|
sendReply(s, &reply, nil)
|
||||||
}
|
break loop
|
||||||
if err = sendReply(s, &reply, nil); err != nil {
|
|
||||||
_ = err
|
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
|
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) {
|
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 (
|
import (
|
||||||
"github.com/criyle/go-judger/types/rlimit"
|
"github.com/criyle/go-judger/types/rlimit"
|
||||||
|
"github.com/criyle/go-judger/types/specs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cmd is the control message send into deamon
|
// Cmd is the control message send into deamon
|
||||||
@ -49,6 +50,7 @@ type Cmd struct {
|
|||||||
|
|
||||||
// Reply is the reply message send back to controller
|
// Reply is the reply message send back to controller
|
||||||
type Reply struct {
|
type Reply struct {
|
||||||
Error string // empty if no error
|
Error string // empty if no error
|
||||||
Status int // waitpid exit status
|
ExitStatus int // waitpid exit status
|
||||||
|
TraceStatus specs.TraceCode // TraceCode
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/criyle/go-judger/types/rlimit"
|
"github.com/criyle/go-judger/types/rlimit"
|
||||||
|
"github.com/criyle/go-judger/types/specs"
|
||||||
"github.com/criyle/go-judger/unixsocket"
|
"github.com/criyle/go-judger/unixsocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ type ExecveParam struct {
|
|||||||
// Wait channel will produce the waitpid exit status
|
// Wait channel will produce the waitpid exit status
|
||||||
// Kill channel will kill the process if value received
|
// Kill channel will kill the process if value received
|
||||||
type ExecveStatus struct {
|
type ExecveStatus struct {
|
||||||
Wait <-chan int
|
Wait <-chan specs.TraceResult
|
||||||
Kill chan<- int
|
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 {
|
if err := m.sendCmd(&Cmd{Cmd: cmdOk}, nil); err != nil {
|
||||||
return nil, fmt.Errorf("execve: ok failed(%v)", err)
|
return nil, fmt.Errorf("execve: ok failed(%v)", err)
|
||||||
}
|
}
|
||||||
wait := make(chan int)
|
wait := make(chan specs.TraceResult)
|
||||||
kill := make(chan int)
|
kill := make(chan int)
|
||||||
// Wait
|
// Wait
|
||||||
go func() {
|
go func() {
|
||||||
reply2, _, err2 := m.recvReply()
|
reply2, _, _ := m.recvReply()
|
||||||
if err2 != nil {
|
wait <- specs.TraceResult{
|
||||||
_ = err2
|
ExitCode: reply2.ExitStatus,
|
||||||
|
TraceStatus: reply2.TraceStatus,
|
||||||
}
|
}
|
||||||
wait <- reply2.Status
|
// done signal (should recv after kill)
|
||||||
|
m.recvReply()
|
||||||
|
close(wait)
|
||||||
}()
|
}()
|
||||||
// Kill
|
// Kill
|
||||||
go func() {
|
go func() {
|
||||||
<-kill
|
<-kill
|
||||||
err3 := m.sendCmd(&Cmd{Cmd: cmdKill}, nil)
|
m.sendCmd(&Cmd{Cmd: cmdKill}, nil)
|
||||||
if err3 != nil {
|
|
||||||
_ = err3
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
return &ExecveStatus{
|
return &ExecveStatus{
|
||||||
Wait: wait,
|
Wait: wait,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user