VNC

From CRIU
Revision as of 02:28, 8 April 2019 by Radostin (talk | contribs) (→‎Video Demo)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Here's the step-by-step description of how to C/R a VNC server with some app inside.

Start VNC server and application[edit]

This should be done carefully.

  • First, X software uses SystemV IPC shared memory to exchange data between server and application, thus you'll have to run the whole stuff in IPC namespace;
  • Second, in order to be restored reliably, it's recommended to run VNC server, window manager and application in a PID namespace;
  • Third, when started from shell they will inherit session ID and terminal from that shell, which might block dump.

That said, we recommend you to run VNC and others using the program below:

newns.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <signal.h>
#include <sched.h>

#define STACK_SIZE	(8 * 4096)

static int ac;
static char **av;
static int ns_exec(void *_arg)
{
	int fd;

	fd = open("newns.log", O_CREAT | O_TRUNC | O_RDWR | O_APPEND, 0600);
	if (fd >= 0) {
		close(0);
		dup2(fd, 1);
		dup2(fd, 2);
		close(fd);
	}

	setsid();
	execvp(av[1], av + 1);
	return 1;
}

int main(int argc, char **argv)
{
	void *stack;
	pid_t pid;

	ac = argc;
	av = argv;

	stack = mmap(NULL, STACK_SIZE, PROT_WRITE | PROT_READ,
			MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS, -1, 0);
	if (stack == MAP_FAILED) {
		fprintf(stderr, "Can't map stack %m\n");
		exit(1);
	}
	pid = clone(ns_exec, stack + STACK_SIZE,
			CLONE_NEWPID | CLONE_NEWIPC | SIGCHLD, NULL);
	if (pid < 0) {
		fprintf(stderr, "clone() failed: %m\n");
		exit(1);
	}
	return 0;
}

it will create necessary namespaces, will create a new session and will redirect stdio to newns.log file. Of course, the same effect is better to be achieved by creating an OpenVZ or LXC container with vzctl, but for quick demo the above proggie is enough.

To run the vnc server and an application in it you can use this script:

#!/bin/bash
set -m
Xvnc :25 -v -geometry 800x600 -interface 0.0.0.0 -SecurityTypes none &
pid=$!
trap "kill $pid; wait" EXIT
sleep 3
DISPLAY=:25 $@

with the above "software" the server can be launched like this:

# chmod a+x vnc_server.sh
# ./newns ./vnc_server.sh icewm

After this you will see the process tree like below:

17854 ?        Ss     0:00 /bin/bash ./vnc-server.sh icewm
17855 ?        Sl     0:00  \_ Xvnc :25 -v -geometry 800x600 -SecurityTypes none
17863 ?        R      0:00  \_ icewm

Launch VNC client[edit]

After this you can start your favorite VNC client (viewer) to see what's inside the server. The latter would be visible on port 5925 (:25 argument). For example:

$ vncviewer localhost:25

Vnc.jpg

Launch a terminal, then some application. It will attach to X and you'd see it on the screen.

Dump VNC and others[edit]

Then you should create a directory for image files (e.g. imgs) and dump the tree starting from the VNC launching script

# criu dump -t 17854 --images-dir imgs/ --log-file dump.log -v4 --tcp-established


The -v4 option is required to make criu more verbose and the --tcp-established one is needed, to make criu handle active TCP connection -- the one between VNC server and VNC client.

Check the criu return code to be 0, or the imgs/dump.log file last message to be

Dumping finished successfully

After this the VNC client would see, that the server got stuck and any moving picture(s) in the screen would be frozen. Hurry up and proceed to the restore stage, as TCP timeout may occur and abort the frozen connection.

Restore VNC server[edit]

# criu restore --images-dir imgs/ --log-file rst.log -v4 --tcp-established -d

What has changed from the dump command is the action (it's restore now), the log file name (not to mix things up) and the new -d option. It says, that after restoring criu should exit and make the restored tree of tasks to be reparented to the init task.

Check the criu return code to be 0, or the imgs/rst.log file last message to be

Restore finished successfully. Resuming tasks.

Video Demo[edit]

Dumping video player with CRIU

Example how CRIU can dump and restore a TCP connections

Checkpoint and restore of Firefox with CRIU

See also[edit]