diff --git a/include/memcached.h b/include/memcached.h
index f9e536eefdc8b535bed3ce9f1d26182c812754cb..2c975791e6c4a013f0f8b9b98fd3f3ae3f11ed87 100644
--- a/include/memcached.h
+++ b/include/memcached.h
@@ -35,6 +35,9 @@ struct tarantool_cfg;
 void
 memcached_init(const char *bind_ipaddr, int memcached_port);
 
+void
+memcached_free(void);
+
 void
 memcached_space_init();
 
diff --git a/src/box/box.cc b/src/box/box.cc
index 00bf4ed46d158cc59e1379a0abb9e8167569851f..a0c244bcf632b6d15810e7187688e053e626046b 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -321,7 +321,6 @@ void
 box_init(bool init_storage)
 {
 	title("loading");
-	atexit(box_free);
 
 	/* initialization spaces */
 	space_init();
diff --git a/src/box/space.cc b/src/box/space.cc
index 3ee39e0ca830d689371baf277ce7dc96b1b48d9a..304324d0a01d7f1d36a389144465b983b09f4d90 100644
--- a/src/box/space.cc
+++ b/src/box/space.cc
@@ -209,6 +209,8 @@ space_validate_tuple(struct space *sp, struct tuple *new_tuple)
 void
 space_free(void)
 {
+	if (spaces == NULL)
+		return;
 	while (mh_size(spaces) > 0) {
 		mh_int_t i = mh_first(spaces);
 
diff --git a/src/memcached.cc b/src/memcached.cc
index 1311fac54f6921e8a4c64e0c90e99e2ecbcea679..545bbeae8cb6df6af1263dc7045da63cd45663eb 100644
--- a/src/memcached.cc
+++ b/src/memcached.cc
@@ -469,7 +469,7 @@ memcached_check_config(struct tarantool_cfg *conf)
 	return 0;
 }
 
-static void
+void
 memcached_free(void)
 {
 	if (memcached_it)
@@ -483,8 +483,6 @@ memcached_init(const char *bind_ipaddr, int memcached_port)
 	if (memcached_port == 0)
 		return;
 
-	atexit(memcached_free);
-
 	stat_base = stat_register(memcached_stat_strs, memcached_stat_MAX);
 
 	struct space *sp = space_by_n(cfg.memcached_space);
diff --git a/src/tarantool.cc b/src/tarantool.cc
index 03f8d913db0ea6958d9c8e9cabd173428a75f99c..aa6bf66e2967b120795ffabefc293a416819c248 100644
--- a/src/tarantool.cc
+++ b/src/tarantool.cc
@@ -316,12 +316,6 @@ tarantool_uptime(void)
 	return ev_now() - start_time;
 }
 
-void snapshot_exit(int code, void* arg) {
-	(void)arg;
-	fflush(NULL);
-	_exit(code);
-}
-
 int
 snapshot(void)
 {
@@ -360,7 +354,6 @@ snapshot(void)
 	 * may call exit(), push a top-level handler which will do
 	 * _exit() for us.
 	 */
-	on_exit(snapshot_exit, NULL);
 	snapshot_save(recovery_state, box_snapshot);
 
 	exit(EXIT_SUCCESS);
@@ -523,7 +516,6 @@ signal_init(void)
 	ev_signal_init(&sigs[3], signal_cb, SIGHUP);
 	ev_signal_start(&sigs[3]);
 
-	atexit(signal_free);
 	(void) tt_pthread_atfork(NULL, NULL, signal_reset);
 }
 
@@ -611,6 +603,13 @@ tarantool_lua_free()
 void
 tarantool_free(void)
 {
+	/* Do nothing in a fork. */
+	if (getpid() != master_pid)
+		return;
+	signal_free();
+	memcached_free();
+	tarantool_lua_free();
+	box_free();
 	recovery_free();
 	stat_free();
 
@@ -867,7 +866,6 @@ main(int argc, char **argv)
 		say_crit("version %s", tarantool_version());
 		tarantool_L = tarantool_lua_init();
 		box_init(false);
-		atexit(tarantool_lua_free);
 		memcached_init(cfg.bind_ipaddr, cfg.memcached_port);
 		tarantool_lua_load_cfg(tarantool_L, &cfg);
 		/*