|
8 | 8 | "fmt" |
9 | 9 | "io" |
10 | 10 | "io/ioutil" |
| 11 | + "net" |
11 | 12 | "os" |
12 | 13 | "os/exec" |
13 | 14 | "path/filepath" |
@@ -727,20 +728,21 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error { |
727 | 728 | defer imageDir.Close() |
728 | 729 |
|
729 | 730 | rpcOpts := criurpc.CriuOpts{ |
730 | | - ImagesDirFd: proto.Int32(int32(imageDir.Fd())), |
731 | | - WorkDirFd: proto.Int32(int32(workDir.Fd())), |
732 | | - LogLevel: proto.Int32(4), |
733 | | - LogFile: proto.String("dump.log"), |
734 | | - Root: proto.String(c.config.Rootfs), |
735 | | - ManageCgroups: proto.Bool(true), |
736 | | - NotifyScripts: proto.Bool(true), |
737 | | - Pid: proto.Int32(int32(c.initProcess.pid())), |
738 | | - ShellJob: proto.Bool(criuOpts.ShellJob), |
739 | | - LeaveRunning: proto.Bool(criuOpts.LeaveRunning), |
740 | | - TcpEstablished: proto.Bool(criuOpts.TcpEstablished), |
741 | | - ExtUnixSk: proto.Bool(criuOpts.ExternalUnixConnections), |
742 | | - FileLocks: proto.Bool(criuOpts.FileLocks), |
743 | | - EmptyNs: proto.Uint32(criuOpts.EmptyNs), |
| 731 | + ImagesDirFd: proto.Int32(int32(imageDir.Fd())), |
| 732 | + WorkDirFd: proto.Int32(int32(workDir.Fd())), |
| 733 | + LogLevel: proto.Int32(4), |
| 734 | + LogFile: proto.String("dump.log"), |
| 735 | + Root: proto.String(c.config.Rootfs), |
| 736 | + ManageCgroups: proto.Bool(true), |
| 737 | + NotifyScripts: proto.Bool(true), |
| 738 | + Pid: proto.Int32(int32(c.initProcess.pid())), |
| 739 | + ShellJob: proto.Bool(criuOpts.ShellJob), |
| 740 | + LeaveRunning: proto.Bool(criuOpts.LeaveRunning), |
| 741 | + TcpEstablished: proto.Bool(criuOpts.TcpEstablished), |
| 742 | + ExtUnixSk: proto.Bool(criuOpts.ExternalUnixConnections), |
| 743 | + FileLocks: proto.Bool(criuOpts.FileLocks), |
| 744 | + EmptyNs: proto.Uint32(criuOpts.EmptyNs), |
| 745 | + OrphanPtsMaster: proto.Bool(true), |
744 | 746 | } |
745 | 747 |
|
746 | 748 | // append optional criu opts, e.g., page-server and port |
@@ -923,20 +925,21 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error { |
923 | 925 | req := &criurpc.CriuReq{ |
924 | 926 | Type: &t, |
925 | 927 | Opts: &criurpc.CriuOpts{ |
926 | | - ImagesDirFd: proto.Int32(int32(imageDir.Fd())), |
927 | | - WorkDirFd: proto.Int32(int32(workDir.Fd())), |
928 | | - EvasiveDevices: proto.Bool(true), |
929 | | - LogLevel: proto.Int32(4), |
930 | | - LogFile: proto.String("restore.log"), |
931 | | - RstSibling: proto.Bool(true), |
932 | | - Root: proto.String(root), |
933 | | - ManageCgroups: proto.Bool(true), |
934 | | - NotifyScripts: proto.Bool(true), |
935 | | - ShellJob: proto.Bool(criuOpts.ShellJob), |
936 | | - ExtUnixSk: proto.Bool(criuOpts.ExternalUnixConnections), |
937 | | - TcpEstablished: proto.Bool(criuOpts.TcpEstablished), |
938 | | - FileLocks: proto.Bool(criuOpts.FileLocks), |
939 | | - EmptyNs: proto.Uint32(criuOpts.EmptyNs), |
| 928 | + ImagesDirFd: proto.Int32(int32(imageDir.Fd())), |
| 929 | + WorkDirFd: proto.Int32(int32(workDir.Fd())), |
| 930 | + EvasiveDevices: proto.Bool(true), |
| 931 | + LogLevel: proto.Int32(4), |
| 932 | + LogFile: proto.String("restore.log"), |
| 933 | + RstSibling: proto.Bool(true), |
| 934 | + Root: proto.String(root), |
| 935 | + ManageCgroups: proto.Bool(true), |
| 936 | + NotifyScripts: proto.Bool(true), |
| 937 | + ShellJob: proto.Bool(criuOpts.ShellJob), |
| 938 | + ExtUnixSk: proto.Bool(criuOpts.ExternalUnixConnections), |
| 939 | + TcpEstablished: proto.Bool(criuOpts.TcpEstablished), |
| 940 | + FileLocks: proto.Bool(criuOpts.FileLocks), |
| 941 | + EmptyNs: proto.Uint32(criuOpts.EmptyNs), |
| 942 | + OrphanPtsMaster: proto.Bool(true), |
940 | 943 | }, |
941 | 944 | } |
942 | 945 |
|
@@ -1037,6 +1040,11 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts * |
1037 | 1040 |
|
1038 | 1041 | logPath := filepath.Join(opts.WorkDirectory, req.GetOpts().GetLogFile()) |
1039 | 1042 | criuClient := os.NewFile(uintptr(fds[0]), "criu-transport-client") |
| 1043 | + criuClientCon, err := net.FileConn(criuClient) |
| 1044 | + if err != nil { |
| 1045 | + return err |
| 1046 | + } |
| 1047 | + |
1040 | 1048 | criuServer := os.NewFile(uintptr(fds[1]), "criu-transport-server") |
1041 | 1049 | defer criuClient.Close() |
1042 | 1050 | defer criuServer.Close() |
@@ -1101,14 +1109,15 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts * |
1101 | 1109 | if err != nil { |
1102 | 1110 | return err |
1103 | 1111 | } |
1104 | | - _, err = criuClient.Write(data) |
| 1112 | + _, err = criuClientCon.Write(data) |
1105 | 1113 | if err != nil { |
1106 | 1114 | return err |
1107 | 1115 | } |
1108 | 1116 |
|
1109 | 1117 | buf := make([]byte, 10*4096) |
| 1118 | + oob := make([]byte, 4096) |
1110 | 1119 | for true { |
1111 | | - n, err := criuClient.Read(buf) |
| 1120 | + n, oobn, _, _, err := criuClientCon.(*net.UnixConn).ReadMsgUnix(buf, oob) |
1112 | 1121 | if err != nil { |
1113 | 1122 | return err |
1114 | 1123 | } |
@@ -1136,7 +1145,7 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts * |
1136 | 1145 | criuFeatures = resp.GetFeatures() |
1137 | 1146 | break |
1138 | 1147 | case t == criurpc.CriuReqType_NOTIFY: |
1139 | | - if err := c.criuNotifications(resp, process, opts, extFds); err != nil { |
| 1148 | + if err := c.criuNotifications(resp, process, opts, extFds, oob[:oobn]); err != nil { |
1140 | 1149 | return err |
1141 | 1150 | } |
1142 | 1151 | t = criurpc.CriuReqType_NOTIFY |
@@ -1220,11 +1229,12 @@ func unlockNetwork(config *configs.Config) error { |
1220 | 1229 | return nil |
1221 | 1230 | } |
1222 | 1231 |
|
1223 | | -func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Process, opts *CriuOpts, fds []string) error { |
| 1232 | +func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Process, opts *CriuOpts, fds []string, oob []byte) error { |
1224 | 1233 | notify := resp.GetNotify() |
1225 | 1234 | if notify == nil { |
1226 | 1235 | return fmt.Errorf("invalid response: %s", resp.String()) |
1227 | 1236 | } |
| 1237 | + logrus.Debugf("notify: %s\n", notify.GetScript()) |
1228 | 1238 | switch { |
1229 | 1239 | case notify.GetScript() == "post-dump": |
1230 | 1240 | f, err := os.Create(filepath.Join(c.root, "checkpoint")) |
@@ -1277,6 +1287,20 @@ func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Proc |
1277 | 1287 | logrus.Error(err) |
1278 | 1288 | } |
1279 | 1289 | } |
| 1290 | + case notify.GetScript() == "orphan-pts-master": |
| 1291 | + scm, err := syscall.ParseSocketControlMessage(oob) |
| 1292 | + if err != nil { |
| 1293 | + return err |
| 1294 | + } |
| 1295 | + fds, err := syscall.ParseUnixRights(&scm[0]) |
| 1296 | + |
| 1297 | + master := os.NewFile(uintptr(fds[0]), "orphan-pts-master") |
| 1298 | + defer master.Close() |
| 1299 | + |
| 1300 | + // While we can access console.master, using the API is a good idea. |
| 1301 | + if err := utils.SendFd(process.ConsoleSocket, master); err != nil { |
| 1302 | + return err |
| 1303 | + } |
1280 | 1304 | } |
1281 | 1305 | return nil |
1282 | 1306 | } |
|
0 commit comments