[CRIU] [PATCH 1/2] libcriu: Add ability to request for notifications from service

Pavel Emelyanov xemul at parallels.com
Wed Jun 25 08:36:14 PDT 2014


This is achieved by supplying the callback. Every time a notification
arrives the callback is called. Return value of 0 means continue,
any other value aborst the request and the value is reported back
to the caller (from criu_dump/criu_restore calls).

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 lib/criu.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 lib/criu.h |  1 +
 2 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/lib/criu.c b/lib/criu.c
index 4b1be8a..a827671 100644
--- a/lib/criu.c
+++ b/lib/criu.c
@@ -19,6 +19,7 @@ const char *criu_lib_version = CRIU_VERSION;
 
 static char *service_address = CR_DEFAULT_SERVICE_ADDRESS;
 static CriuOpts *opts;
+static int (*notify)(char *action);
 static int saved_errno;
 
 void criu_set_service_address(char *path)
@@ -31,8 +32,10 @@ void criu_set_service_address(char *path)
 
 int criu_init_opts(void)
 {
-	if (opts)
+	if (opts) {
+		notify = NULL;
 		criu_opts__free_unpacked(opts, NULL);
+	}
 
 	opts = malloc(sizeof(CriuOpts));
 	if (opts == NULL) {
@@ -44,6 +47,13 @@ int criu_init_opts(void)
 	return 0;
 }
 
+void criu_set_notify(int (*cb)(char *action))
+{
+	notify = cb;
+	opts->has_notify_scripts = true;
+	opts->notify_scripts = true;
+}
+
 void criu_set_pid(int pid)
 {
 	opts->has_pid	= true;
@@ -192,6 +202,29 @@ err:
 	return -1;
 }
 
+static int send_notify_ack(int socket_fd, int ret)
+{
+	int send_ret;
+	CriuReq req = CRIU_REQ__INIT;
+
+	req.type = CRIU_REQ_TYPE__NOTIFY;
+	req.has_notify_success = true;
+	req.notify_success = (ret == 0);
+
+	send_ret = send_req(socket_fd, &req);
+
+	/*
+	 * If we're failing the notification then report
+	 * back the original error code (and it will be
+	 * propagated back to user).
+	 *
+	 * If the notification was OK, then report the
+	 * result of acking it.
+	 */
+
+	return ret ? : send_ret;
+}
+
 static int criu_connect(void)
 {
 	int fd, ret;
@@ -228,29 +261,41 @@ static int send_req_and_recv_resp_sk(int fd, CriuReq *req, CriuResp **resp)
 	int ret = 0;
 
 	if (send_req(fd, req) < 0) {
-		ret = ECOMM;
+		ret = -ECOMM;
 		goto exit;
 	}
 
+again:
 	*resp = recv_resp(fd);
 	if (!*resp) {
 		perror("Can't receive response");
-		ret = ECOMM;
+		ret = -ECOMM;
 		goto exit;
 	}
 
+	if ((*resp)->type == CRIU_REQ_TYPE__NOTIFY) {
+		if (notify)
+			ret = notify((*resp)->notify->script);
+
+		ret = send_notify_ack(fd, ret);
+		if (!ret)
+			goto again;
+		else
+			goto exit;
+	}
+
 	if ((*resp)->type != req->type) {
 		if ((*resp)->type == CRIU_REQ_TYPE__EMPTY &&
 		    (*resp)->success == false)
-			ret = EINVAL;
+			ret = -EINVAL;
 		else {
 			perror("Unexpected response type");
-			ret = EBADMSG;
+			ret = -EBADMSG;
 		}
 	}
 
 exit:
-	return -ret;
+	return ret;
 }
 
 static int send_req_and_recv_resp(CriuReq *req, CriuResp **resp)
diff --git a/lib/criu.h b/lib/criu.h
index 7c33897..c994fd6 100644
--- a/lib/criu.h
+++ b/lib/criu.h
@@ -42,6 +42,7 @@ void criu_set_log_level(int log_level);
 void criu_set_log_file(char *log_file);
 void criu_set_cpu_cap(unsigned int cap);
 int criu_set_exec_cmd(int argc, char *argv[]);
+void criu_set_notify(int (*cb)(char *action));
 
 /* Here is a table of return values and errno's of functions
  * from the list down below.
-- 
1.8.4.2




More information about the CRIU mailing list