[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(¶m);
> 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(¶m);
> param.ioctlfd = mnt_fd;
> param.setpipefd.pipefd = second_pipe[1];
>
> err = ioctl(fd, AUTOFS_DEV_IOCTL_SETPIPEFD, ¶m);
> 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