crtools: close a signal descriptor after passing a preparation stage

Submitted by Andrei Vagin on Nov. 17, 2016, 6:35 a.m.

Details

Message ID 1479364501-11927-1-git-send-email-avagin@openvz.org
State Superseded
Series "crtools: close a signal descriptor after passing a preparation stage"
Headers show

Commit Message

Andrei Vagin Nov. 17, 2016, 6:35 a.m.
From: Andrei Vagin <avagin@virtuozzo.com>

This patch adds the --siganl-fd FD option to specify a file descriptor.
CRIU will write '\0' to this descriptor and close it after passing
a preparation stage.

It is alternative way to demonizing a criu process after a preparation
stage. It's imposiable to get exit code, if a process has daemonized.

The introduced way allows to wait a preparation stage and to get an exit
code. It can be easy used from shell and other script languages.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
---
 criu/crtools.c            | 13 ++++++++++++-
 criu/include/cr_options.h |  1 +
 criu/include/util.h       |  1 +
 criu/uffd.c               |  3 +++
 criu/util.c               | 18 ++++++++++++++++++
 5 files changed, 35 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/criu/crtools.c b/criu/crtools.c
index 710059f..6c468f6 100644
--- a/criu/crtools.c
+++ b/criu/crtools.c
@@ -55,7 +55,9 @@ 
 
 #include "../soccr/soccr.h"
 
-struct cr_options opts;
+struct cr_options opts = {
+	.status_fd = -1,
+};
 
 void init_opts(void)
 {
@@ -285,6 +287,7 @@  int main(int argc, char *argv[], char *envp[])
 		{ "deprecated",			no_argument,		0, 1084 },
 		{ "check-only",			no_argument,		0, 1085 },
 		{ "display-stats",		no_argument,		0, 1086 },
+		{ "status-fd",			required_argument,	0, 1087 },
 		{ },
 	};
 
@@ -608,6 +611,12 @@  int main(int argc, char *argv[], char *envp[])
 		case 1086:
 			opts.display_stats = true;
 			break;
+		case 1087:
+			if (sscanf(optarg, "%d", &opts.status_fd) != 1) {
+				pr_err("Unable to parse a value of --status-fd\n");
+				return 1;
+			}
+			break;
 		case 'V':
 			pr_msg("Version: %s\n", CRIU_VERSION);
 			if (strcmp(CRIU_GITID, "0"))
@@ -945,6 +954,8 @@  usage:
 "  --address ADDR        address of server or service\n"
 "  --port PORT           port of page server\n"
 "  -d|--daemon           run in the background after creating socket\n"
+"  --status-fd FD        write '\\0' and close FD after passing a preparation\n"
+"                        stage\n"
 "\n"
 "Other options:\n"
 "  -h|--help             show this text\n"
diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h
index e017236..abebe05 100644
--- a/criu/include/cr_options.h
+++ b/criu/include/cr_options.h
@@ -118,6 +118,7 @@  struct cr_options {
 	bool			deprecated_ok;
 	bool			display_stats;
 	bool			check_only;
+	int			status_fd;
 };
 
 extern struct cr_options opts;
diff --git a/criu/include/util.h b/criu/include/util.h
index 8eaee33..ea1053b 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -170,6 +170,7 @@  extern int cr_system(int in, int out, int err, char *cmd, char *const argv[], un
 extern int cr_system_userns(int in, int out, int err, char *cmd,
 				char *const argv[], unsigned flags, int userns_pid);
 extern int cr_daemon(int nochdir, int noclose, int *keep_fd, int close_fd);
+extern int close_status_fd(void);
 extern int is_root_user(void);
 
 static inline bool dir_dots(const struct dirent *de)
diff --git a/criu/uffd.c b/criu/uffd.c
index 7efccf5..ba81f4b 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -1031,6 +1031,9 @@  int cr_lazy_pages(bool daemon)
 		}
 	}
 
+	if (close_status_fd())
+		return -1;
+
 	nr_fds = epoll_nr_fds(task_entries->nr_tasks);
 	epollfd = prepare_epoll(nr_fds, &events);
 	if (epollfd < 0)
diff --git a/criu/util.c b/criu/util.c
index 2cf0355..4ecfd4d 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -687,6 +687,21 @@  out:
 	return ret;
 }
 
+int close_status_fd(void)
+{
+	int c = 0;
+
+	if (opts.status_fd < 0)
+		return 0;
+
+	if (write(opts.status_fd, &c, 1) != 1) {
+		pr_perror("Unable to write into the status fd");
+		return -1;
+	}
+
+	return close_safe(&opts.status_fd);
+}
+
 int cr_daemon(int nochdir, int noclose, int *keep_fd, int close_fd)
 {
 	int pid;
@@ -1144,6 +1159,9 @@  int run_tcp_server(bool daemon_mode, int *ask, int cfd, int sk)
 		}
 	}
 
+	if (close_status_fd())
+		return -1;
+
 	if (sk >= 0) {
 		ret = *ask = accept(sk, (struct sockaddr *)&caddr, &clen);
 		if (*ask < 0)

Comments

Kir Kolyshkin Nov. 17, 2016, 7:24 a.m.
On 11/16/2016 10:35 PM, Andrei Vagin wrote:
> From: Andrei Vagin <avagin@virtuozzo.com>
>
> This patch adds the --siganl-fd FD option to specify a file descriptor.
> CRIU will write '\0' to this descriptor and close it after passing
> a preparation stage.
>
> It is alternative way to demonizing a criu process after a preparation
> stage. It's imposiable to get exit code, if a process has daemonized.
>
> The introduced way allows to wait a preparation stage and to get an exit
> code. It can be easy used from shell and other script languages.
>
> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
> ---
>   criu/crtools.c            | 13 ++++++++++++-
>   criu/include/cr_options.h |  1 +
>   criu/include/util.h       |  1 +
>   criu/uffd.c               |  3 +++
>   criu/util.c               | 18 ++++++++++++++++++
>   5 files changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/criu/crtools.c b/criu/crtools.c
> index 710059f..6c468f6 100644
> --- a/criu/crtools.c
> +++ b/criu/crtools.c
> @@ -55,7 +55,9 @@
>   
>   #include "../soccr/soccr.h"
>   
> -struct cr_options opts;
> +struct cr_options opts = {
> +	.status_fd = -1,
> +};
>   
>   void init_opts(void)
>   {
> @@ -285,6 +287,7 @@ int main(int argc, char *argv[], char *envp[])
>   		{ "deprecated",			no_argument,		0, 1084 },
>   		{ "check-only",			no_argument,		0, 1085 },
>   		{ "display-stats",		no_argument,		0, 1086 },
> +		{ "status-fd",			required_argument,	0, 1087 },
>   		{ },
>   	};
>   
> @@ -608,6 +611,12 @@ int main(int argc, char *argv[], char *envp[])
>   		case 1086:
>   			opts.display_stats = true;
>   			break;
> +		case 1087:
> +			if (sscanf(optarg, "%d", &opts.status_fd) != 1) {
> +				pr_err("Unable to parse a value of --status-fd\n");
> +				return 1;
> +			}
> +			break;
>   		case 'V':
>   			pr_msg("Version: %s\n", CRIU_VERSION);
>   			if (strcmp(CRIU_GITID, "0"))
> @@ -945,6 +954,8 @@ usage:
>   "  --address ADDR        address of server or service\n"
>   "  --port PORT           port of page server\n"
>   "  -d|--daemon           run in the background after creating socket\n"
> +"  --status-fd FD        write '\\0' and close FD after passing a preparation\n"
> +"                        stage\n"

"write \0 to and close FD once daemon is ready"

Also, try hard to fit help text in a single line. If needed, longer
explanation can be provided in other places like the man page
and wiki.

>   "\n"
>   "Other options:\n"
>   "  -h|--help             show this text\n"
> diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h
> index e017236..abebe05 100644
> --- a/criu/include/cr_options.h
> +++ b/criu/include/cr_options.h
> @@ -118,6 +118,7 @@ struct cr_options {
>   	bool			deprecated_ok;
>   	bool			display_stats;
>   	bool			check_only;
> +	int			status_fd;
>   };
>   
>   extern struct cr_options opts;
> diff --git a/criu/include/util.h b/criu/include/util.h
> index 8eaee33..ea1053b 100644
> --- a/criu/include/util.h
> +++ b/criu/include/util.h
> @@ -170,6 +170,7 @@ extern int cr_system(int in, int out, int err, char *cmd, char *const argv[], un
>   extern int cr_system_userns(int in, int out, int err, char *cmd,
>   				char *const argv[], unsigned flags, int userns_pid);
>   extern int cr_daemon(int nochdir, int noclose, int *keep_fd, int close_fd);
> +extern int close_status_fd(void);
>   extern int is_root_user(void);
>   
>   static inline bool dir_dots(const struct dirent *de)
> diff --git a/criu/uffd.c b/criu/uffd.c
> index 7efccf5..ba81f4b 100644
> --- a/criu/uffd.c
> +++ b/criu/uffd.c
> @@ -1031,6 +1031,9 @@ int cr_lazy_pages(bool daemon)
>   		}
>   	}
>   
> +	if (close_status_fd())
> +		return -1;
> +
>   	nr_fds = epoll_nr_fds(task_entries->nr_tasks);
>   	epollfd = prepare_epoll(nr_fds, &events);
>   	if (epollfd < 0)
> diff --git a/criu/util.c b/criu/util.c
> index 2cf0355..4ecfd4d 100644
> --- a/criu/util.c
> +++ b/criu/util.c
> @@ -687,6 +687,21 @@ out:
>   	return ret;
>   }
>   
> +int close_status_fd(void)
> +{
> +	int c = 0;
> +
> +	if (opts.status_fd < 0)
> +		return 0;
> +
> +	if (write(opts.status_fd, &c, 1) != 1) {
> +		pr_perror("Unable to write into the status fd");
> +		return -1;
> +	}
> +
> +	return close_safe(&opts.status_fd);
> +}
> +
>   int cr_daemon(int nochdir, int noclose, int *keep_fd, int close_fd)
>   {
>   	int pid;
> @@ -1144,6 +1159,9 @@ int run_tcp_server(bool daemon_mode, int *ask, int cfd, int sk)
>   		}
>   	}
>   
> +	if (close_status_fd())
> +		return -1;
> +
>   	if (sk >= 0) {
>   		ret = *ask = accept(sk, (struct sockaddr *)&caddr, &clen);
>   		if (*ask < 0)
otherwise
Reviewed-by: Kir Kolyshkin <kir@openvz.org>
Mike Rapoport Nov. 17, 2016, 8:30 a.m.
On Thu, Nov 17, 2016 at 9:24 AM, Kir Kolyshkin <kir@openvz.org> wrote:
>
> On 11/16/2016 10:35 PM, Andrei Vagin wrote:
>>
>> From: Andrei Vagin <avagin@virtuozzo.com>
>>
>> This patch adds the --siganl-fd FD option to specify a file descriptor.
>> CRIU will write '\0' to this descriptor and close it after passing
>> a preparation stage.
>>
>> It is alternative way to demonizing a criu process after a preparation
>> stage. It's imposiable to get exit code, if a process has daemonized.
>>
>> The introduced way allows to wait a preparation stage and to get an exit
>> code. It can be easy used from shell and other script languages.
>>
>> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
>> ---
>>   criu/crtools.c            | 13 ++++++++++++-
>>   criu/include/cr_options.h |  1 +
>>   criu/include/util.h       |  1 +
>>   criu/uffd.c               |  3 +++
>>   criu/util.c               | 18 ++++++++++++++++++
>>   5 files changed, 35 insertions(+), 1 deletion(-)
>>
>> diff --git a/criu/crtools.c b/criu/crtools.c
>> index 710059f..6c468f6 100644
>> --- a/criu/crtools.c
>> +++ b/criu/crtools.c
>> @@ -55,7 +55,9 @@
>>     #include "../soccr/soccr.h"
>>   -struct cr_options opts;
>> +struct cr_options opts = {
>> +       .status_fd = -1,
>> +};
>>     void init_opts(void)
>>   {
>> @@ -285,6 +287,7 @@ int main(int argc, char *argv[], char *envp[])
>>                 { "deprecated",                 no_argument,            0,
>> 1084 },
>>                 { "check-only",                 no_argument,            0,
>> 1085 },
>>                 { "display-stats",              no_argument,            0,
>> 1086 },
>> +               { "status-fd",                  required_argument,      0,
>> 1087 },
>>                 { },
>>         };
>>   @@ -608,6 +611,12 @@ int main(int argc, char *argv[], char *envp[])
>>                 case 1086:
>>                         opts.display_stats = true;
>>                         break;
>> +               case 1087:
>> +                       if (sscanf(optarg, "%d", &opts.status_fd) != 1) {
>> +                               pr_err("Unable to parse a value of
>> --status-fd\n");
>> +                               return 1;
>> +                       }
>> +                       break;
>>                 case 'V':
>>                         pr_msg("Version: %s\n", CRIU_VERSION);
>>                         if (strcmp(CRIU_GITID, "0"))
>> @@ -945,6 +954,8 @@ usage:
>>   "  --address ADDR        address of server or service\n"
>>   "  --port PORT           port of page server\n"
>>   "  -d|--daemon           run in the background after creating socket\n"
>> +"  --status-fd FD        write '\\0' and close FD after passing a
>> preparation\n"
>> +"                        stage\n"
>
>
> "write \0 to and close FD once daemon is ready"

"write \0 to the FD and close it once daemon is ready"

> Also, try hard to fit help text in a single line. If needed, longer
> explanation can be provided in other places like the man page
> and wiki.
>
>
>>   "\n"
>>   "Other options:\n"
>>   "  -h|--help             show this text\n"
>> diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h
>> index e017236..abebe05 100644
>> --- a/criu/include/cr_options.h
>> +++ b/criu/include/cr_options.h
>> @@ -118,6 +118,7 @@ struct cr_options {
>>         bool                    deprecated_ok;
>>         bool                    display_stats;
>>         bool                    check_only;
>> +       int                     status_fd;
>>   };
>>     extern struct cr_options opts;
>> diff --git a/criu/include/util.h b/criu/include/util.h
>> index 8eaee33..ea1053b 100644
>> --- a/criu/include/util.h
>> +++ b/criu/include/util.h
>> @@ -170,6 +170,7 @@ extern int cr_system(int in, int out, int err, char
>> *cmd, char *const argv[], un
>>   extern int cr_system_userns(int in, int out, int err, char *cmd,
>>                                 char *const argv[], unsigned flags, int
>> userns_pid);
>>   extern int cr_daemon(int nochdir, int noclose, int *keep_fd, int
>> close_fd);
>> +extern int close_status_fd(void);
>>   extern int is_root_user(void);
>>     static inline bool dir_dots(const struct dirent *de)
>> diff --git a/criu/uffd.c b/criu/uffd.c
>> index 7efccf5..ba81f4b 100644
>> --- a/criu/uffd.c
>> +++ b/criu/uffd.c
>> @@ -1031,6 +1031,9 @@ int cr_lazy_pages(bool daemon)
>>                 }
>>         }
>>   +     if (close_status_fd())
>> +               return -1;
>> +
>>         nr_fds = epoll_nr_fds(task_entries->nr_tasks);
>>         epollfd = prepare_epoll(nr_fds, &events);
>>         if (epollfd < 0)
>> diff --git a/criu/util.c b/criu/util.c
>> index 2cf0355..4ecfd4d 100644
>> --- a/criu/util.c
>> +++ b/criu/util.c
>> @@ -687,6 +687,21 @@ out:
>>         return ret;
>>   }
>>   +int close_status_fd(void)
>> +{
>> +       int c = 0;
>> +
>> +       if (opts.status_fd < 0)
>> +               return 0;
>> +
>> +       if (write(opts.status_fd, &c, 1) != 1) {
>> +               pr_perror("Unable to write into the status fd");
>> +               return -1;
>> +       }
>> +
>> +       return close_safe(&opts.status_fd);
>> +}
>> +
>>   int cr_daemon(int nochdir, int noclose, int *keep_fd, int close_fd)
>>   {
>>         int pid;
>> @@ -1144,6 +1159,9 @@ int run_tcp_server(bool daemon_mode, int *ask, int
>> cfd, int sk)
>>                 }
>>         }
>>   +     if (close_status_fd())
>> +               return -1;
>> +
>>         if (sk >= 0) {
>>                 ret = *ask = accept(sk, (struct sockaddr *)&caddr, &clen);
>>                 if (*ask < 0)
>
> otherwise
> Reviewed-by: Kir Kolyshkin <kir@openvz.org>
>
> _______________________________________________
> CRIU mailing list
> CRIU@openvz.org
> https://lists.openvz.org/mailman/listinfo/criu