diff --git a/include/fiber.h b/include/fiber.h
index 0d31a830de9bb9313d1e3426c2e75a73341b7c28..49dda87f2f3fd0d6a075271ca481c6b3978b2b30 100644
--- a/include/fiber.h
+++ b/include/fiber.h
@@ -95,7 +95,8 @@ extern __thread struct fiber *fiber;
 
 void fiber_init(void);
 void fiber_free(void);
-struct fiber *fiber_new(const char *name, void (*f) (va_list));
+typedef void(*fiber_func)(va_list);
+struct fiber *fiber_new(const char *name, fiber_func f);
 void fiber_set_name(struct fiber *fiber, const char *name);
 int wait_for_child(pid_t pid);
 
diff --git a/include/tarantool.h b/include/tarantool.h
index 6da91c9b2e49e213c40e2e1acc62fd65af5ff368..b9eda2655216e50cdf2ad03e6ac529439826f155 100644
--- a/include/tarantool.h
+++ b/include/tarantool.h
@@ -43,7 +43,7 @@ extern char *binary_filename;
 extern char *custom_proc_title;
 i32 reload_cfg(struct tbuf *out);
 void show_cfg(struct tbuf *out);
-int snapshot(void * /* ev */, int /* events */);
+int snapshot(void);
 const char *tarantool_version(void);
 double tarantool_uptime(void);
 void tarantool_free(void);
diff --git a/src/admin.m b/src/admin.m
index 8b50cdf28a3e8413283a0e82ffabab54d17bf704..361eebaa919932ce01c442cfc7c20889c4c7fadc 100644
--- a/src/admin.m
+++ b/src/admin.m
@@ -328,7 +328,7 @@ tr67:
 tr76:
 #line 244 "src/admin.rl"
 	{
-			int ret = snapshot(NULL, 0);
+			int ret = snapshot();
 
 			if (ret == 0)
 				ok(out);
@@ -453,7 +453,7 @@ tr68:
 tr77:
 #line 244 "src/admin.rl"
 	{
-			int ret = snapshot(NULL, 0);
+			int ret = snapshot();
 
 			if (ret == 0)
 				ok(out);
diff --git a/src/admin.rl b/src/admin.rl
index 9ad64f03a3c68d4af83dfc728c7989c6f4d70ca4..5172efcfb6a69dc8a05ac6256c5441add27e9a23 100644
--- a/src/admin.rl
+++ b/src/admin.rl
@@ -242,7 +242,7 @@ admin_dispatch(struct ev_io *coio, struct iobuf *iobuf, lua_State *L)
 		}
 
 		action save_snapshot {
-			int ret = snapshot(NULL, 0);
+			int ret = snapshot();
 
 			if (ret == 0)
 				ok(out);
diff --git a/src/tarantool.m b/src/tarantool.m
index 2601f873e5aa2fbb891e2583520055cf90461f8b..75b76036b90a079188e5c5a452d7300ce84f86db 100644
--- a/src/tarantool.m
+++ b/src/tarantool.m
@@ -316,7 +316,7 @@ tarantool_uptime(void)
 }
 
 int
-snapshot(void *ev, int events __attribute__((unused)))
+snapshot(void)
 {
 	if (snapshot_pid)
 		return EINPROGRESS;
@@ -327,22 +327,6 @@ snapshot(void *ev, int events __attribute__((unused)))
 		return -1;
 	}
 	if (p > 0) {
-		/*
-		 * If called from a signal handler, we can't
-		 * access any fiber state, and no one is expecting
-		 * to get an execution status. Just return 0 to
-		 * indicate a successful fork.
-		 */
-		if (ev != NULL)
-			return 0;
-		/*
-		 * This is 'save snapshot' call received from the
-		 * administrative console. Check for the child
-		 * exit status and report it back. This is done to
-		 * make 'save snapshot' synchronous, and propagate
-		 * any possible error up to the user.
-		 */
-
 		snapshot_pid = p;
 		int status = wait_for_child(p);
 		snapshot_pid = 0;
@@ -363,6 +347,22 @@ snapshot(void *ev, int events __attribute__((unused)))
 	return 0;
 }
 
+
+/**
+* Create snapshot from signal handler (SIGUSR1)
+*
+*/
+static void
+sig_snapshot(void)
+{
+	if (snapshot_pid) {
+		say_warn("Snapshot process is already running,"
+			" the signal is ignored");
+		return;
+	}
+	fiber_call(fiber_new("snapshot", (fiber_func)snapshot));
+}
+
 static void
 signal_cb(void)
 {
@@ -489,7 +489,7 @@ signal_init(void)
 
 	sigs = palloc(eter_pool, sizeof(ev_signal) * 4);
 	memset(sigs, 0, sizeof(ev_signal) * 4);
-	ev_signal_init(&sigs[0], (void*)snapshot, SIGUSR1);
+	ev_signal_init(&sigs[0], (void*)sig_snapshot, SIGUSR1);
 	ev_signal_start(&sigs[0]);
 	ev_signal_init(&sigs[1], (void*)signal_cb, SIGINT);
 	ev_signal_start(&sigs[1]);