88 "fmt"
99 "io"
1010 "io/ioutil"
11+ "net"
1112 "os"
1213 "os/exec"
1314 "path/filepath"
@@ -676,20 +677,21 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
676677 defer imageDir .Close ()
677678
678679 rpcOpts := criurpc.CriuOpts {
679- ImagesDirFd : proto .Int32 (int32 (imageDir .Fd ())),
680- WorkDirFd : proto .Int32 (int32 (workDir .Fd ())),
681- LogLevel : proto .Int32 (4 ),
682- LogFile : proto .String ("dump.log" ),
683- Root : proto .String (c .config .Rootfs ),
684- ManageCgroups : proto .Bool (true ),
685- NotifyScripts : proto .Bool (true ),
686- Pid : proto .Int32 (int32 (c .initProcess .pid ())),
687- ShellJob : proto .Bool (criuOpts .ShellJob ),
688- LeaveRunning : proto .Bool (criuOpts .LeaveRunning ),
689- TcpEstablished : proto .Bool (criuOpts .TcpEstablished ),
690- ExtUnixSk : proto .Bool (criuOpts .ExternalUnixConnections ),
691- FileLocks : proto .Bool (criuOpts .FileLocks ),
692- EmptyNs : proto .Uint32 (criuOpts .EmptyNs ),
680+ ImagesDirFd : proto .Int32 (int32 (imageDir .Fd ())),
681+ WorkDirFd : proto .Int32 (int32 (workDir .Fd ())),
682+ LogLevel : proto .Int32 (4 ),
683+ LogFile : proto .String ("dump.log" ),
684+ Root : proto .String (c .config .Rootfs ),
685+ ManageCgroups : proto .Bool (true ),
686+ NotifyScripts : proto .Bool (true ),
687+ Pid : proto .Int32 (int32 (c .initProcess .pid ())),
688+ ShellJob : proto .Bool (criuOpts .ShellJob ),
689+ LeaveRunning : proto .Bool (criuOpts .LeaveRunning ),
690+ TcpEstablished : proto .Bool (criuOpts .TcpEstablished ),
691+ ExtUnixSk : proto .Bool (criuOpts .ExternalUnixConnections ),
692+ FileLocks : proto .Bool (criuOpts .FileLocks ),
693+ EmptyNs : proto .Uint32 (criuOpts .EmptyNs ),
694+ OrphanPtsMaster : proto .Bool (true ),
693695 }
694696
695697 // append optional criu opts, e.g., page-server and port
@@ -864,20 +866,21 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
864866 req := & criurpc.CriuReq {
865867 Type : & t ,
866868 Opts : & criurpc.CriuOpts {
867- ImagesDirFd : proto .Int32 (int32 (imageDir .Fd ())),
868- WorkDirFd : proto .Int32 (int32 (workDir .Fd ())),
869- EvasiveDevices : proto .Bool (true ),
870- LogLevel : proto .Int32 (4 ),
871- LogFile : proto .String ("restore.log" ),
872- RstSibling : proto .Bool (true ),
873- Root : proto .String (root ),
874- ManageCgroups : proto .Bool (true ),
875- NotifyScripts : proto .Bool (true ),
876- ShellJob : proto .Bool (criuOpts .ShellJob ),
877- ExtUnixSk : proto .Bool (criuOpts .ExternalUnixConnections ),
878- TcpEstablished : proto .Bool (criuOpts .TcpEstablished ),
879- FileLocks : proto .Bool (criuOpts .FileLocks ),
880- EmptyNs : proto .Uint32 (criuOpts .EmptyNs ),
869+ ImagesDirFd : proto .Int32 (int32 (imageDir .Fd ())),
870+ WorkDirFd : proto .Int32 (int32 (workDir .Fd ())),
871+ EvasiveDevices : proto .Bool (true ),
872+ LogLevel : proto .Int32 (4 ),
873+ LogFile : proto .String ("restore.log" ),
874+ RstSibling : proto .Bool (true ),
875+ Root : proto .String (root ),
876+ ManageCgroups : proto .Bool (true ),
877+ NotifyScripts : proto .Bool (true ),
878+ ShellJob : proto .Bool (criuOpts .ShellJob ),
879+ ExtUnixSk : proto .Bool (criuOpts .ExternalUnixConnections ),
880+ TcpEstablished : proto .Bool (criuOpts .TcpEstablished ),
881+ FileLocks : proto .Bool (criuOpts .FileLocks ),
882+ EmptyNs : proto .Uint32 (criuOpts .EmptyNs ),
883+ OrphanPtsMaster : proto .Bool (true ),
881884 },
882885 }
883886
@@ -974,6 +977,11 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
974977
975978 logPath := filepath .Join (opts .WorkDirectory , req .GetOpts ().GetLogFile ())
976979 criuClient := os .NewFile (uintptr (fds [0 ]), "criu-transport-client" )
980+ criuClientCon , err := net .FileConn (criuClient )
981+ if err != nil {
982+ return err
983+ }
984+
977985 criuServer := os .NewFile (uintptr (fds [1 ]), "criu-transport-server" )
978986 defer criuClient .Close ()
979987 defer criuServer .Close ()
@@ -1033,14 +1041,15 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
10331041 if err != nil {
10341042 return err
10351043 }
1036- _ , err = criuClient .Write (data )
1044+ _ , err = criuClientCon .Write (data )
10371045 if err != nil {
10381046 return err
10391047 }
10401048
10411049 buf := make ([]byte , 10 * 4096 )
1050+ oob := make ([]byte , 4096 )
10421051 for true {
1043- n , err := criuClient . Read ( buf )
1052+ n , oobn , _ , _ , err := criuClientCon .( * net. UnixConn ). ReadMsgUnix ( buf , oob )
10441053 if err != nil {
10451054 return err
10461055 }
@@ -1064,7 +1073,7 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
10641073 t := resp .GetType ()
10651074 switch {
10661075 case t == criurpc .CriuReqType_NOTIFY :
1067- if err := c .criuNotifications (resp , process , opts , extFds ); err != nil {
1076+ if err := c .criuNotifications (resp , process , opts , extFds , oob [: oobn ] ); err != nil {
10681077 return err
10691078 }
10701079 t = criurpc .CriuReqType_NOTIFY
@@ -1148,11 +1157,12 @@ func unlockNetwork(config *configs.Config) error {
11481157 return nil
11491158}
11501159
1151- func (c * linuxContainer ) criuNotifications (resp * criurpc.CriuResp , process * Process , opts * CriuOpts , fds []string ) error {
1160+ func (c * linuxContainer ) criuNotifications (resp * criurpc.CriuResp , process * Process , opts * CriuOpts , fds []string , oob [] byte ) error {
11521161 notify := resp .GetNotify ()
11531162 if notify == nil {
11541163 return fmt .Errorf ("invalid response: %s" , resp .String ())
11551164 }
1165+ logrus .Debugf ("notify: %s\n " , notify .GetScript ())
11561166 switch {
11571167 case notify .GetScript () == "post-dump" :
11581168 f , err := os .Create (filepath .Join (c .root , "checkpoint" ))
@@ -1205,6 +1215,20 @@ func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Proc
12051215 logrus .Error (err )
12061216 }
12071217 }
1218+ case notify .GetScript () == "orphan-pts-master" :
1219+ scm , err := syscall .ParseSocketControlMessage (oob )
1220+ if err != nil {
1221+ return err
1222+ }
1223+ fds , err := syscall .ParseUnixRights (& scm [0 ])
1224+
1225+ master := os .NewFile (uintptr (fds [0 ]), "orphan-pts-master" )
1226+ defer master .Close ()
1227+
1228+ // While we can access console.master, using the API is a good idea.
1229+ if err := utils .SendFd (process .ConsoleSocket , master ); err != nil {
1230+ return err
1231+ }
12081232 }
12091233 return nil
12101234}
0 commit comments