Index: uspace/app/tester/proc/task_anywait.c
===================================================================
--- uspace/app/tester/proc/task_anywait.c	(revision b22b0a94b341e922fce473e92cec4901af1e7086)
+++ uspace/app/tester/proc/task_anywait.c	(revision b8341bc21ab560e485c8aac4f5a0d1473851664c)
@@ -102,5 +102,6 @@
 	int rc;
 
-	task_set_event_handler(task_event_handler);
+	rc = task_register_event_handler(task_event_handler);
+	TASSERT(rc == EOK);
 
 	TPRINTF("1 exit only\n");
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision b22b0a94b341e922fce473e92cec4901af1e7086)
+++ uspace/lib/c/generic/task.c	(revision b8341bc21ab560e485c8aac4f5a0d1473851664c)
@@ -472,8 +472,70 @@
 }
 
-void task_set_event_handler(task_event_handler_t handler)
-{
+// TODO extract to separate module
+static void taskman_task_event(ipc_callid_t iid, ipc_call_t *icall)
+{
+	task_id_t tid = (task_id_t)
+	    MERGE_LOUP32(IPC_GET_ARG1(*icall), IPC_GET_ARG2(*icall));
+	int flags = IPC_GET_ARG3(*icall);
+	task_exit_t texit = IPC_GET_ARG4(*icall);
+	int retval = IPC_GET_ARG5(*icall);
+
+	task_event_handler(tid, flags, texit, retval);
+
+	async_answer_0(iid, EOK);
+}
+
+static void taskman_event_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Accept connection */
+	async_answer_0(iid, EOK);
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			/* Hangup, TODO explain or handle differntly */
+			break;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case TASKMAN_EV_TASK:
+			taskman_task_event(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}
+}
+
+/**
+ * Blocks, calls handler in another fibril
+ */
+int task_register_event_handler(task_event_handler_t handler)
+{
+	/*
+	 * so far support assign once, modification cannot be naïve due to
+	 * races
+	 */
+	assert(task_event_handler == NULL);
+	assert(handler != NULL); /* no support for "unregistration" */
+
 	task_event_handler = handler;
-	// TODO implement logic for calling the handler
+
+	async_exch_t *exch = taskman_exchange_begin();
+	aid_t req = async_send_0(exch, TASKMAN_EVENT_CALLBACK, NULL);
+
+	int rc = async_connect_to_me(exch, 0, 0, 0, taskman_event_conn, NULL);
+	taskman_exchange_end(exch);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	return retval;
 }
 
Index: uspace/lib/c/include/ipc/taskman.h
===================================================================
--- uspace/lib/c/include/ipc/taskman.h	(revision b22b0a94b341e922fce473e92cec4901af1e7086)
+++ uspace/lib/c/include/ipc/taskman.h	(revision b8341bc21ab560e485c8aac4f5a0d1473851664c)
@@ -41,6 +41,11 @@
 typedef enum {
 	TASKMAN_WAIT = IPC_FIRST_USER_METHOD,
-	TASKMAN_RETVAL
+	TASKMAN_RETVAL,
+	TASKMAN_EVENT_CALLBACK
 } taskman_request_t;
+
+typedef enum {
+	TASKMAN_EV_TASK = IPC_FIRST_USER_METHOD
+} taskman_event_t;
 
 typedef enum {
Index: uspace/lib/c/include/task.h
===================================================================
--- uspace/lib/c/include/task.h	(revision b22b0a94b341e922fce473e92cec4901af1e7086)
+++ uspace/lib/c/include/task.h	(revision b8341bc21ab560e485c8aac4f5a0d1473851664c)
@@ -75,5 +75,5 @@
 
 extern errno_t task_retval(int);
-extern void task_set_event_handler(task_event_handler_t);
+extern int task_register_event_handler(task_event_handler_t);
 
 #endif
Index: uspace/srv/taskman/main.c
===================================================================
--- uspace/srv/taskman/main.c	(revision b22b0a94b341e922fce473e92cec4901af1e7086)
+++ uspace/srv/taskman/main.c	(revision b8341bc21ab560e485c8aac4f5a0d1473851664c)
@@ -79,5 +79,7 @@
 	async_exchange_end(exch);
 
-	/* After forward we can dispose all session-related resources */
+	/* After forward we can dispose all session-related resources
+	 * TODO later could be recycled for notification API
+	 */
 	async_hangup(sess_ref->sess);
 	free(sess_ref);
@@ -118,4 +120,10 @@
 	int rc = task_set_retval(icall);
 	async_answer_0(iid, rc);
+}
+
+static void taskman_ctl_ev_callback(ipc_callid_t iid, ipc_call_t *icall)
+{
+	printf("%s:%i from %llu\n", __func__, __LINE__, icall->in_task_id);
+	async_answer_0(iid, ENOTSUP); // TODO interrupt here
 }
 
@@ -152,4 +160,7 @@
 		case TASKMAN_RETVAL:
 			taskman_ctl_retval(callid, &call);
+			break;
+		case TASKMAN_EVENT_CALLBACK:
+			taskman_ctl_ev_callback(callid, &call);
 			break;
 		default:
@@ -223,7 +234,4 @@
 	case TASKMAN_CONTROL:
 		control_connection(iid, icall);
-		// ---- interrupt here ----
-		//   implement control connection body (setup wait)
-		// ------------------------
 		break;
 	default:
