Index: uspace/app/sysctl/main.c
===================================================================
--- uspace/app/sysctl/main.c	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/app/sysctl/main.c	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -39,4 +39,5 @@
 #include <str_error.h>
 #include <sysman/ctl.h>
+#include <unistd.h>
 
 #define NAME "sysctl"
@@ -141,8 +142,23 @@
 }
 
+static int shutdown(int argc, char *argv[])
+{
+	const int delay = 3;
+	printf("Will shutdown in %i seconds...\n", delay);
+	sleep(delay);
+	printf("Shutdown now.\n");
+
+	int rc = sysman_shutdown();
+	if (rc != EOK) {
+		printf("Shutdown request failed: %s.\n", str_error(rc));
+	}
+	return rc;
+}
+
 command_t commands[] = {
 	{ "list-units", 0, &list_units },
 	{ "start",      1, &start },
 	{ "stop",       1, &stop },
+	{ "shutdown",   0, &shutdown },
 	{ 0 }
 };
Index: uspace/lib/c/include/ipc/sysman.h
===================================================================
--- uspace/lib/c/include/ipc/sysman.h	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/lib/c/include/ipc/sysman.h	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -50,5 +50,6 @@
 	SYSMAN_CTL_GET_UNITS,
 	SYSMAN_CTL_UNIT_GET_NAME,
-	SYSMAN_CTL_UNIT_GET_STATE
+	SYSMAN_CTL_UNIT_GET_STATE,
+	SYSMAN_CTL_SHUTDOWN
 } sysman_ipc_method_t;
 
Index: uspace/lib/sysman/include/sysman/ctl.h
===================================================================
--- uspace/lib/sysman/include/sysman/ctl.h	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/lib/sysman/include/sysman/ctl.h	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -43,3 +43,5 @@
 int sysman_unit_get_name(unit_handle_t, char *, size_t);
 int sysman_unit_get_state(unit_handle_t, unit_state_t *);
+
+int sysman_shutdown(void);
 #endif
Index: uspace/lib/sysman/src/ctl.c
===================================================================
--- uspace/lib/sysman/src/ctl.c	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/lib/sysman/src/ctl.c	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -192,2 +192,11 @@
 	return rc;
 }
+
+int sysman_shutdown(void)
+{
+	async_exch_t *exch = sysman_exchange_begin(SYSMAN_PORT_CTL);
+	int rc = async_req_0_0(exch, SYSMAN_CTL_SHUTDOWN);
+	sysman_exchange_end(exch);
+
+	return rc;
+}
Index: uspace/srv/sysman/Makefile
===================================================================
--- uspace/srv/sysman/Makefile	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/srv/sysman/Makefile	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -46,4 +46,5 @@
 	log.c \
 	repo.c \
+	shutdown.c \
 	sm_task.c \
 	sysman.c \
Index: uspace/srv/sysman/connection_ctl.c
===================================================================
--- uspace/srv/sysman/connection_ctl.c	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/srv/sysman/connection_ctl.c	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -36,5 +36,7 @@
 #include "connection_ctl.h"
 #include "job.h"
+#include "job_closure.h"
 #include "log.h"
+#include "shutdown.h"
 #include "sysman.h"
 
@@ -114,5 +116,5 @@
 
 	if (!(flags & IPC_FLAG_BLOCKING)) {
-		retval = sysman_run_job(unit, STATE_STARTED, NULL, NULL);
+		retval = sysman_run_job(unit, STATE_STARTED, 0, NULL, NULL);
 		goto answer;
 	}
@@ -123,5 +125,5 @@
 		goto answer;
 	}
-	retval = sysman_run_job(unit, STATE_STARTED, &answer_callback,
+	retval = sysman_run_job(unit, STATE_STARTED, 0, &answer_callback,
 	    iid_ptr);
 	if (retval != EOK) {
@@ -154,5 +156,5 @@
 
 	if (!(flags & IPC_FLAG_BLOCKING)) {
-		retval = sysman_run_job(unit, state, NULL, NULL);
+		retval = sysman_run_job(unit, state, 0, NULL, NULL);
 		goto answer;
 	}
@@ -163,5 +165,5 @@
 		goto answer;
 	}
-	retval = sysman_run_job(unit, state, &answer_callback,
+	retval = sysman_run_job(unit, state, 0, &answer_callback,
 	    iid_ptr);
 	if (retval != EOK) {
@@ -278,4 +280,20 @@
 }
 
+static void sysman_shutdown(ipc_callid_t iid, ipc_call_t *icall)
+{
+	int retval;
+	unit_t *u = repo_find_unit_by_name(TARGET_SHUTDOWN);
+	if (u == NULL) {
+		retval = ENOENT;
+		goto finish;
+	}
+
+	retval = sysman_run_job(u, STATE_STARTED, CLOSURE_ISOLATE,
+	    shutdown_cb, NULL);
+
+finish:
+	async_answer_0(iid, retval);
+}
+
 void sysman_connection_ctl(ipc_callid_t iid, ipc_call_t *icall)
 {
@@ -315,4 +333,7 @@
 			sysman_unit_get_state(callid, &call);
 			break;
+		case SYSMAN_CTL_SHUTDOWN:
+			sysman_shutdown(callid, &call);
+			break;
 		default:
 			async_answer_0(callid, ENOENT);
Index: uspace/srv/sysman/job_closure.c
===================================================================
--- uspace/srv/sysman/job_closure.c	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/srv/sysman/job_closure.c	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -295,5 +295,5 @@
 /** Creates job closure for given basic job
  *
- * @note It is caller's responsibility to clean job_closure (event on error).
+ * @note It is caller's responsibility to clean job_closure (even on error).
  *
  * @return EOK on success otherwise propagated error
Index: uspace/srv/sysman/main.c
===================================================================
--- uspace/srv/sysman/main.c	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/srv/sysman/main.c	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -38,5 +38,4 @@
 #include <taskman.h>
 
-#include "repo.h"
 #include "connection_broker.h"
 #include "connection_ctl.h"
@@ -44,21 +43,10 @@
 #include "job_queue.h"
 #include "log.h"
+#include "repo.h"
+#include "sm_task.h"
 #include "sysman.h"
-#include "sm_task.h"
 #include "unit.h"
 
 #define NAME "sysman"
-
-#define INITRD_DEVICE       "bd/initrd"
-#define INITRD_MOUNT_POINT  "/"
-#define INITRD_CFG_PATH     "/cfg/sysman"
-
-#define TARGET_INIT     "initrd.tgt"
-#define TARGET_ROOTFS   "rootfs.tgt"
-#define TARGET_DEFAULT  "default.tgt"
-
-#define UNIT_MNT_INITRD "initrd.mnt"
-#define UNIT_CFG_INITRD "init.cfg"
-
 
 static const char *target_sequence[] = {
@@ -195,5 +183,5 @@
 	}
 
-	int rc = sysman_run_job(tgt, STATE_STARTED, &sequence_job_handler,
+	int rc = sysman_run_job(tgt, STATE_STARTED, 0, &sequence_job_handler,
 	    target_name_ptr);
 
Index: uspace/srv/sysman/shutdown.c
===================================================================
--- uspace/srv/sysman/shutdown.c	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
+++ uspace/srv/sysman/shutdown.c	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016 Michal Koutny
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <io/console.h>
+#include <str_error.h>
+
+#include "job.h"
+#include "log.h"
+#include "shutdown.h"
+#include "sysman.h"
+
+/** Callback when shutdown job is done
+ *
+ * Possibly delay the job completion until other jobs of the CLOSURE_ISOLATE
+ * are completed.
+ */
+void shutdown_cb(void *object, void *arg)
+{
+	job_t *job = object;
+	assert(job->state == JOB_FINISHED);
+	assert(job->retval != JOB_UNDEFINED_);
+
+	/* Clean any remnants of compositor */
+	console_kcon();
+
+	if (job->retval == JOB_OK) {
+		sysman_log(LVL_NOTE, "Shutdown unit '%s' started.\n",
+		    TARGET_SHUTDOWN);
+	} else {
+		sysman_log(LVL_WARN, "Start of unit '%s' failed (%s).\n",
+		    TARGET_SHUTDOWN, str_error(job->retval));
+	}
+}
Index: uspace/srv/sysman/shutdown.h
===================================================================
--- uspace/srv/sysman/shutdown.h	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
+++ uspace/srv/sysman/shutdown.h	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016 Michal Koutny
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SYSMAN_SHUTDOWN_H
+#define SYSMAN_SHUTDOWN_H
+
+extern void shutdown_cb(void *, void *);
+
+#endif
Index: uspace/srv/sysman/sm_task.c
===================================================================
--- uspace/srv/sysman/sm_task.c	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/srv/sysman/sm_task.c	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -106,4 +106,12 @@
 	 * name */
 
+	/*
+	 * Temporary workaround to avoid killing ourselves during shutdown,
+	 * eventually should be captured by dependencies.
+	 */
+	if (tid == task_get_id() || tid == 2 /*taskman*/) {
+		CAST_SVC(u_svc)->critical = true;
+	}
+
 	repo_begin_update();
 	in_repo_update = true;
Index: uspace/srv/sysman/sysman.c
===================================================================
--- uspace/srv/sysman/sysman.c	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/srv/sysman/sysman.c	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -65,4 +65,5 @@
 typedef struct {
 	job_t *job;
+	int flags;
 	callback_handler_t callback;
 	void *callback_arg;
@@ -205,10 +206,12 @@
  * If unit already has the same job assigned callback is moved to it.
  *
- * @param[in]  callback  (optional) callback must explicitly delete reference
- *                       to job, void callback(void *job, void *callback_arg)
- *
- * return EBUSY  unit already has a job assigned of different type
- */
-int sysman_run_job(unit_t *unit, unit_state_t target_state,
+ * @param[in]  flags        additional flags for job
+ * @param[in]  callback     (optional) callback must explicitly delete reference
+ *                          to job, void callback(void *job, void *callback_arg)
+ * @param[in]  callback_arg
+ *
+ * @return EOK on successfully queued job
+ */
+int sysman_run_job(unit_t *unit, unit_state_t target_state, int flags,
     callback_handler_t callback, void *callback_arg)
 {
@@ -226,4 +229,5 @@
 	/* Pass reference to job_args */
 	job_args->job = job;
+	job_args->flags = flags;
 	job_args->callback = callback;
 	job_args->callback_arg = callback_arg;
@@ -364,4 +368,5 @@
 	job_args_t *job_args = data;
 	job_t *job = job_args->job;
+	int flags = job_args->flags;
 	dyn_array_t job_closure;
 	dyn_array_initialize(&job_closure, job_t *);
@@ -373,5 +378,5 @@
 	free(job_args);
 
-	int rc = job_create_closure(job, &job_closure, 0);
+	int rc = job_create_closure(job, &job_closure, flags);
 	if (rc != EOK) {
 		sysman_log(LVL_ERROR, "Cannot create closure for job %p (%i)",
Index: uspace/srv/sysman/sysman.h
===================================================================
--- uspace/srv/sysman/sysman.h	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/srv/sysman/sysman.h	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -30,4 +30,17 @@
 #define SYSMAN_SYSMAN_H
 
+#define INITRD_DEVICE       "bd/initrd"
+#define INITRD_MOUNT_POINT  "/"
+#define INITRD_CFG_PATH     "/cfg/sysman"
+
+// TODO configurable
+#define TARGET_INIT     "initrd.tgt"
+#define TARGET_ROOTFS   "rootfs.tgt"
+#define TARGET_DEFAULT  "default.tgt"
+#define TARGET_SHUTDOWN "shutdown.tgt"
+
+#define UNIT_MNT_INITRD "initrd.mnt"
+#define UNIT_CFG_INITRD "init.cfg"
+
 #include "job.h"
 #include "unit.h"
@@ -38,5 +51,5 @@
 extern void sysman_events_init(void);
 extern int sysman_events_loop(void *);
-extern int sysman_run_job(unit_t *, unit_state_t, callback_handler_t, void *);
+extern int sysman_run_job(unit_t *, unit_state_t, int, callback_handler_t, void *);
 
 
Index: uspace/srv/sysman/test/job_queue.c
===================================================================
--- uspace/srv/sysman/test/job_queue.c	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/srv/sysman/test/job_queue.c	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -83,5 +83,5 @@
 	job_t *job = NULL;
 
-	int rc = sysman_run_job(u, STATE_STARTED, &job_finished_cb,
+	int rc = sysman_run_job(u, STATE_STARTED, 0, &job_finished_cb,
 	    &job);
 	PCUT_ASSERT_INT_EQUALS(EOK, rc);
@@ -102,5 +102,5 @@
 	job_t *job = NULL;
 
-	int rc = sysman_run_job(u, STATE_STARTED, &job_finished_cb, &job);
+	int rc = sysman_run_job(u, STATE_STARTED, 0, &job_finished_cb, &job);
 	PCUT_ASSERT_INT_EQUALS(EOK, rc);
 
@@ -142,5 +142,5 @@
 	/* Run test */
 	job_t *job = NULL;
-	int rc = sysman_run_job(s1, STATE_STARTED, &job_finished_cb, &job);
+	int rc = sysman_run_job(s1, STATE_STARTED, 0, &job_finished_cb, &job);
 	PCUT_ASSERT_INT_EQUALS(EOK, rc);
 
@@ -163,5 +163,5 @@
 	/* Create and start first job */
 	job_t *j0 = NULL;
-	int rc = sysman_run_job(s0, STATE_STARTED, &job_finished_cb, &j0);
+	int rc = sysman_run_job(s0, STATE_STARTED, 0, &job_finished_cb, &j0);
 	PCUT_ASSERT_INT_EQUALS(EOK, rc);
 
@@ -176,5 +176,5 @@
 	 */
 	job_t *j1 = NULL;
-	rc = sysman_run_job(s0, STATE_STARTED, &job_finished_cb, &j1);
+	rc = sysman_run_job(s0, STATE_STARTED, 0, &job_finished_cb, &j1);
 	PCUT_ASSERT_INT_EQUALS(EOK, rc);
 
Index: uspace/srv/sysman/units/unit_svc.c
===================================================================
--- uspace/srv/sysman/units/unit_svc.c	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/srv/sysman/units/unit_svc.c	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -120,4 +120,13 @@
 	assert(unit->state == STATE_STARTED);
 
+	/*
+	 * Ugly trick -- critical service is running despite being stopped
+	 * circumvent killing ourselves during shutdown (TODO dependencies).
+	 */
+	if (u_svc->critical) {
+		unit->state = STATE_STOPPED;
+		return EOK;
+	}
+
 	int rc = task_kill(u_svc->main_task_id);
 
Index: uspace/srv/sysman/units/unit_svc.h
===================================================================
--- uspace/srv/sysman/units/unit_svc.h	(revision be07995661547b856a461a29a94ec0fbbb5a8fb0)
+++ uspace/srv/sysman/units/unit_svc.h	(revision 8d74fdd2c255a9b8d91060f48eb2a6ff6cc5ad0c)
@@ -43,4 +43,7 @@
 
 	bool anonymous;
+
+	/** Service can't be stopped, temporary workaround for shutdown */
+	bool critical;
 } unit_svc_t;
 
