[CRIU] Process receive -EINTR on epoll_wait() after restore

Andrew Vagin avagin at virtuozzo.com
Tue Dec 8 08:06:18 PST 2015


On Mon, Dec 07, 2015 at 05:18:37PM +0100, Stanislav Kinsburskiy wrote:
> Good day,
> 
> While debugging issues with systemd and AutoFS, I found, that attached
> program receive -EINTR after restore from epoll_wait() system call.
> Unfortunately, without AutoFS restore support in CRIU, it can't be used as a
> reproducer. But the result if 100% reproducible (on each suspend/restore).
> However, I suspect , that receiving -EINTR is not something I should expect.
> Is it true?

It's known issue.

(00.004567) Warn  (arch/x86/crtools.c:133): Will restore 19059 with interrupted system call

> #include <stdio.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <errno.h>
> #include <stdlib.h>
> #include <errno.h>
> #include <string.h>
> #include <sys/epoll.h>
> 
> #define NAME_MAX 256
> #include "auto_dev-ioctl.h"
> 
> int epoll_pipe(int pfd)
> {
> 	int epoll, res;
> 	struct epoll_event event;
> 	unsigned int events_mask = EPOLLIN;
> 
> 	printf("Creating epoll:\n");
> 
> 	epoll = epoll_create(1);
> 	if (epoll < 0) {
> 		printf("Failed to create epoll\n");
> 		return -1;
> 	}
> 
> 	printf("Waiting epoll event:\n");
> 	event.events = events_mask;
> 	event.data.fd = pfd;
> 	if (epoll_ctl(epoll, EPOLL_CTL_ADD, pfd, &event) < 0) {
> 		printf("Failed to create epoll for fd %d\n", pfd);
> 		return -1;
> 	}
> 
> 	while(1) {
> 		res = epoll_wait(epoll, &event, 1, -1);
> 		if (res == 0) {	
> 			printf("epoll timeout!!!\n");
> 			return 0;
> 		}
> 		if (res < 0) {
> 			res = -errno;
> 			printf("epoll failed: %s (%x)\n", strerror(errno), event.events);
> 			if (res != -EINTR)
> 				return -1;
> 		} 
> 	}
> 	printf("Received epoll event: %x\n", event.events);
> 	
> 	return -1;
> }
> int main()
> {
> 	int err;
> 	char options[256];
> 	int first_pipe[2], second_pipe[2];
> 	char *mnt_path = "/mnt", *nested_path = "/mnt/nested";
> 	int fd, mnt_fd;
> 	struct autofs_dev_ioctl param;
> 
> 	if (pipe(first_pipe)) {
> 		printf("failed to open first pipe\n");
> 		exit(1);
> 	}
> 
> 	if (pipe(second_pipe)) {
> 		printf("failed to open second pipe\n");
> 		exit(1);
> 	}
> 
> //	sprintf(options, "fd=%d,pgrp=%d,minproto=5,maxproto=5,indirect", first_pipe[1], getpid());
> 	sprintf(options, "fd=%d,minproto=5,maxproto=5,indirect", first_pipe[1]);
> 
> 	printf("Mounting autofs to %s with %s options\n", mnt_path, options);
> 
> 	err = mount("null", mnt_path, "autofs", 0, options);
> 	if (err) {
> 		printf("failed to mount\n");
> 		exit(1);
> 	}
> 
> 	printf("Closing first_pipe[1]\n");
> 	if (close(first_pipe[1]) < 0) {
> 		printf("failed to close\n");
> 		goto umount;
> 	}
> 
> 	if (epoll_pipe(first_pipe[0]) != 0) {
> 		goto umount;
> 	}
> 
> 	fd = open("/dev/autofs", O_RDONLY);
> 	if (fd == -1) {
> 		printf("failed to open /dev/autofs\n");
> 		goto umount;
> 	}
> 
> 	mnt_fd = open(mnt_path, O_RDONLY | O_DIRECTORY);
> 	if (mnt_fd == -1) {
> 		err = -errno;
> 		printf("failed to open %s", mnt_path);
> 		goto umount;
> 	}
> 
> 	printf("Going to to create nested dir %s\n", nested_path);
> 	getchar();
> 
> 	close(first_pipe[1]);
> 	close(first_pipe[0]);
> 
> 	err = mkdir(nested_path, 0600);
> 	if (mnt_fd == -1) {
> 		err = -errno;
> 		printf("failed to create %s", nested_path);
> 		goto close_fd;
> 	}
> 
> 	printf("Going to mount tmpfs to %s\n", nested_path);
> 	getchar();
> 
> 	err = mount("null", nested_path, "tmpfs", 0, "size=1M");
> 	if (err) {
> 		printf("failed to mount tmpfs\n");
> 		goto close_fd;
> 	}
> 
> 
> 	printf("Going to make device catatonic\n");
> 	getchar();
> 
> 	init_autofs_dev_ioctl(&param);
> 	err = ioctl(mnt_fd, AUTOFS_IOC_CATATONIC, 0);
> 	if (err == -1) {
> 		printf("failed to set mount point catatonic: %d (%s)\n", errno, strerror(errno));
> 		goto umount_tmpfs;
> 
> 	}
> 
> 	printf("Going to replace pipe fd with %d\n", second_pipe[1]);
> 	getchar();
> 
> 	init_autofs_dev_ioctl(&param);
> 	param.ioctlfd = mnt_fd;
> 	param.setpipefd.pipefd = second_pipe[1];
> 
> 	err = ioctl(fd, AUTOFS_DEV_IOCTL_SETPIPEFD, &param);
> 	if (err == -1) {
> 		printf("failed to send ioctl to /dev/autofs: %d (%s)\n", errno, strerror(errno));
> 		goto umount_tmpfs;
> 
> 	}
> 
> 	printf("Going to umount %s\n", mnt_path);
> 	getchar();
> 
> umount_tmpfs:
> 	if (umount(nested_path)) {
> 		printf("failed to umount %s\n", nested_path);
> 	}
> close_fd:
> 	close(mnt_fd);
> umount:
> 	if (umount(mnt_path)) {
> 		printf("failed to umount %s\n", mnt_path);
> 	}
> 	return err;
> }

> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu



More information about the CRIU mailing list