mirror of
https://github.com/criyle/go-sandbox.git
synced 2025-11-04 14:49:53 +08:00
80 lines
1.8 KiB
Go
80 lines
1.8 KiB
Go
package deamon
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/gob"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/criyle/go-judger/unixsocket"
|
|
)
|
|
|
|
// ContainerInit is called for container init process
|
|
// it will check if pid == 1, otherwise it is noop
|
|
// ContainerInit will do infinite loop on socket commands,
|
|
// and exits when at socket close
|
|
func ContainerInit() (err error) {
|
|
// noop if self is not container init process
|
|
if os.Getpid() != 1 {
|
|
return nil
|
|
}
|
|
|
|
// exit process (with whole container) upon exit this function
|
|
defer func() {
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "container_exit: %v", err)
|
|
os.Exit(1)
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, "container_exit")
|
|
os.Exit(0)
|
|
}
|
|
}()
|
|
|
|
// new_master shared the socket at fd 3 (marked close_exec)
|
|
soc, err := unixsocket.NewSocket(3)
|
|
if err != nil {
|
|
return fmt.Errorf("container_init: faile to new socket(%v)", err)
|
|
}
|
|
var (
|
|
buffer = make([]byte, bufferSize)
|
|
cmd Cmd
|
|
)
|
|
for {
|
|
n, msg, err := soc.RecvMsg(buffer)
|
|
if err != nil {
|
|
return fmt.Errorf("loop: failed RecvMsg(%v)", err)
|
|
}
|
|
dec := gob.NewDecoder(bytes.NewReader(buffer[:n]))
|
|
if err := dec.Decode(&cmd); err != nil {
|
|
return fmt.Errorf("loop: failed to decode(%v)", err)
|
|
}
|
|
if err := handleCmd(soc, &cmd, msg); err != nil {
|
|
return fmt.Errorf("loop: failed to execute cmd(%v)", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func handleCmd(s *unixsocket.Socket, cmd *Cmd, msg *unixsocket.Msg) error {
|
|
switch cmd.Cmd {
|
|
case cmdPing:
|
|
return handlePing(s)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func handlePing(s *unixsocket.Socket) error {
|
|
return sendReply(s, &Reply{})
|
|
}
|
|
|
|
func sendReply(s *unixsocket.Socket, reply *Reply) error {
|
|
var buffer bytes.Buffer
|
|
enc := gob.NewEncoder(&buffer)
|
|
if err := enc.Encode(reply); err != nil {
|
|
return err
|
|
}
|
|
if err := s.SendMsg(buffer.Bytes(), nil); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|