88 "fmt"
99 "io"
1010 "io/ioutil"
11+ "net"
1112 "os"
1213 "os/exec"
1314 "path/filepath"
@@ -657,20 +658,21 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
657658 defer imageDir .Close ()
658659
659660 rpcOpts := criurpc.CriuOpts {
660- ImagesDirFd : proto .Int32 (int32 (imageDir .Fd ())),
661- WorkDirFd : proto .Int32 (int32 (workDir .Fd ())),
662- LogLevel : proto .Int32 (4 ),
663- LogFile : proto .String ("dump.log" ),
664- Root : proto .String (c .config .Rootfs ),
665- ManageCgroups : proto .Bool (true ),
666- NotifyScripts : proto .Bool (true ),
667- Pid : proto .Int32 (int32 (c .initProcess .pid ())),
668- ShellJob : proto .Bool (criuOpts .ShellJob ),
669- LeaveRunning : proto .Bool (criuOpts .LeaveRunning ),
670- TcpEstablished : proto .Bool (criuOpts .TcpEstablished ),
671- ExtUnixSk : proto .Bool (criuOpts .ExternalUnixConnections ),
672- FileLocks : proto .Bool (criuOpts .FileLocks ),
673- EmptyNs : proto .Uint32 (criuOpts .EmptyNs ),
661+ ImagesDirFd : proto .Int32 (int32 (imageDir .Fd ())),
662+ WorkDirFd : proto .Int32 (int32 (workDir .Fd ())),
663+ LogLevel : proto .Int32 (4 ),
664+ LogFile : proto .String ("dump.log" ),
665+ Root : proto .String (c .config .Rootfs ),
666+ ManageCgroups : proto .Bool (true ),
667+ NotifyScripts : proto .Bool (true ),
668+ Pid : proto .Int32 (int32 (c .initProcess .pid ())),
669+ ShellJob : proto .Bool (criuOpts .ShellJob ),
670+ LeaveRunning : proto .Bool (criuOpts .LeaveRunning ),
671+ TcpEstablished : proto .Bool (criuOpts .TcpEstablished ),
672+ ExtUnixSk : proto .Bool (criuOpts .ExternalUnixConnections ),
673+ FileLocks : proto .Bool (criuOpts .FileLocks ),
674+ EmptyNs : proto .Uint32 (criuOpts .EmptyNs ),
675+ OrphanPtsMaster : proto .Bool (true ),
674676 }
675677
676678 // append optional criu opts, e.g., page-server and port
@@ -838,20 +840,21 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
838840 req := & criurpc.CriuReq {
839841 Type : & t ,
840842 Opts : & criurpc.CriuOpts {
841- ImagesDirFd : proto .Int32 (int32 (imageDir .Fd ())),
842- WorkDirFd : proto .Int32 (int32 (workDir .Fd ())),
843- EvasiveDevices : proto .Bool (true ),
844- LogLevel : proto .Int32 (4 ),
845- LogFile : proto .String ("restore.log" ),
846- RstSibling : proto .Bool (true ),
847- Root : proto .String (root ),
848- ManageCgroups : proto .Bool (true ),
849- NotifyScripts : proto .Bool (true ),
850- ShellJob : proto .Bool (criuOpts .ShellJob ),
851- ExtUnixSk : proto .Bool (criuOpts .ExternalUnixConnections ),
852- TcpEstablished : proto .Bool (criuOpts .TcpEstablished ),
853- FileLocks : proto .Bool (criuOpts .FileLocks ),
854- EmptyNs : proto .Uint32 (criuOpts .EmptyNs ),
843+ ImagesDirFd : proto .Int32 (int32 (imageDir .Fd ())),
844+ WorkDirFd : proto .Int32 (int32 (workDir .Fd ())),
845+ EvasiveDevices : proto .Bool (true ),
846+ LogLevel : proto .Int32 (4 ),
847+ LogFile : proto .String ("restore.log" ),
848+ RstSibling : proto .Bool (true ),
849+ Root : proto .String (root ),
850+ ManageCgroups : proto .Bool (true ),
851+ NotifyScripts : proto .Bool (true ),
852+ ShellJob : proto .Bool (criuOpts .ShellJob ),
853+ ExtUnixSk : proto .Bool (criuOpts .ExternalUnixConnections ),
854+ TcpEstablished : proto .Bool (criuOpts .TcpEstablished ),
855+ FileLocks : proto .Bool (criuOpts .FileLocks ),
856+ EmptyNs : proto .Uint32 (criuOpts .EmptyNs ),
857+ OrphanPtsMaster : proto .Bool (true ),
855858 },
856859 }
857860
@@ -947,6 +950,11 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
947950
948951 logPath := filepath .Join (opts .WorkDirectory , req .GetOpts ().GetLogFile ())
949952 criuClient := os .NewFile (uintptr (fds [0 ]), "criu-transport-client" )
953+ criuClientCon , err := net .FileConn (criuClient )
954+ if err != nil {
955+ return err
956+ }
957+
950958 criuServer := os .NewFile (uintptr (fds [1 ]), "criu-transport-server" )
951959 defer criuClient .Close ()
952960 defer criuServer .Close ()
@@ -1006,14 +1014,15 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
10061014 if err != nil {
10071015 return err
10081016 }
1009- _ , err = criuClient .Write (data )
1017+ _ , err = criuClientCon .Write (data )
10101018 if err != nil {
10111019 return err
10121020 }
10131021
10141022 buf := make ([]byte , 10 * 4096 )
1023+ oob := make ([]byte , 4096 )
10151024 for true {
1016- n , err := criuClient . Read ( buf )
1025+ n , oobn , _ , _ , err := criuClientCon .( * net. UnixConn ). ReadMsgUnix ( buf , oob )
10171026 if err != nil {
10181027 return err
10191028 }
@@ -1037,7 +1046,7 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
10371046 t := resp .GetType ()
10381047 switch {
10391048 case t == criurpc .CriuReqType_NOTIFY :
1040- if err := c .criuNotifications (resp , process , opts , extFds ); err != nil {
1049+ if err := c .criuNotifications (resp , process , opts , extFds , oob [: oobn ] ); err != nil {
10411050 return err
10421051 }
10431052 t = criurpc .CriuReqType_NOTIFY
@@ -1121,11 +1130,12 @@ func unlockNetwork(config *configs.Config) error {
11211130 return nil
11221131}
11231132
1124- func (c * linuxContainer ) criuNotifications (resp * criurpc.CriuResp , process * Process , opts * CriuOpts , fds []string ) error {
1133+ func (c * linuxContainer ) criuNotifications (resp * criurpc.CriuResp , process * Process , opts * CriuOpts , fds []string , oob [] byte ) error {
11251134 notify := resp .GetNotify ()
11261135 if notify == nil {
11271136 return fmt .Errorf ("invalid response: %s" , resp .String ())
11281137 }
1138+ logrus .Debugf ("notify: %s\n " , notify .GetScript ())
11291139 switch {
11301140 case notify .GetScript () == "post-dump" :
11311141 f , err := os .Create (filepath .Join (c .root , "checkpoint" ))
@@ -1178,6 +1188,20 @@ func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Proc
11781188 logrus .Error (err )
11791189 }
11801190 }
1191+ case notify .GetScript () == "orphan-pts-master" :
1192+ scm , err := syscall .ParseSocketControlMessage (oob )
1193+ if err != nil {
1194+ return err
1195+ }
1196+ fds , err := syscall .ParseUnixRights (& scm [0 ])
1197+
1198+ master := os .NewFile (uintptr (fds [0 ]), "orphan-pts-master" )
1199+ defer master .Close ()
1200+
1201+ // While we can access console.master, using the API is a good idea.
1202+ if err := utils .SendFd (process .ConsoleSocket , master ); err != nil {
1203+ return err
1204+ }
11811205 }
11821206 return nil
11831207}
0 commit comments