Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 0b005997aa705c5c511941d3a843eab28f34def7)
+++ kernel/generic/src/ipc/ipc.c	(revision 97b8ca970e38244c08a9fa57840bd46ae9acfb8f)
@@ -328,16 +328,21 @@
 }
 
-static void _ipc_call_actions_internal(phone_t *phone, call_t *call)
+static void _ipc_call_actions_internal(phone_t *phone, call_t *call,
+    bool preforget)
 {
 	task_t *caller = phone->caller;
 
-	atomic_inc(&phone->active_calls);
 	call->caller_phone = phone;
-	call->sender = caller;
-
-	call->active = true;
-	spinlock_lock(&caller->active_calls_lock);
-	list_append(&call->ta_link, &caller->active_calls);
-	spinlock_unlock(&caller->active_calls_lock);
+
+	if (preforget) {
+		call->forget = true;
+	} else {
+		atomic_inc(&phone->active_calls);
+		call->sender = caller;
+		call->active = true;
+		spinlock_lock(&caller->active_calls_lock);
+		list_append(&call->ta_link, &caller->active_calls);
+		spinlock_unlock(&caller->active_calls_lock);
+	}
 
 	call->data.phone = phone;
@@ -357,5 +362,5 @@
 void ipc_backsend_err(phone_t *phone, call_t *call, sysarg_t err)
 {
-	_ipc_call_actions_internal(phone, call);
+	_ipc_call_actions_internal(phone, call, false);
 	IPC_SET_RETVAL(call->data, err);
 	_ipc_answer_free_call(call, false);
@@ -364,10 +369,12 @@
 /** Unsafe unchecking version of ipc_call.
  *
- * @param phone Phone structure the call comes from.
- * @param box   Destination answerbox structure.
- * @param call  Call structure with request.
- *
- */
-static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call)
+ * @param phone     Phone structure the call comes from.
+ * @param box       Destination answerbox structure.
+ * @param call      Call structure with request.
+ * @param preforget If true, the call will be delivered already forgotten.
+ *
+ */
+static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call,
+    bool preforget)
 {
 	task_t *caller = phone->caller;
@@ -379,5 +386,5 @@
 	
 	if (!(call->flags & IPC_CALL_FORWARDED))
-		_ipc_call_actions_internal(phone, call);
+		_ipc_call_actions_internal(phone, call, preforget);
 	
 	irq_spinlock_lock(&box->lock, true);
@@ -413,5 +420,5 @@
 	
 	answerbox_t *box = phone->callee;
-	_ipc_call(phone, box, call);
+	_ipc_call(phone, box, call, false);
 	
 	mutex_unlock(&phone->lock);
@@ -451,5 +458,5 @@
 		call->request_method = IPC_M_PHONE_HUNGUP;
 		call->flags |= IPC_CALL_DISCARD_ANSWER;
-		_ipc_call(phone, box, call);
+		_ipc_call(phone, box, call, false);
 	}
 	
@@ -610,6 +617,4 @@
 	phone_t *phone;
 	DEADLOCK_PROBE_INIT(p_phonelck);
-	
-	call_t *call = notify_box ? ipc_call_alloc(0) : NULL;
 	
 	/* Disconnect all phones connected to our answerbox */
@@ -632,22 +637,22 @@
 		
 		if (notify_box) {
+			task_hold(phone->caller);
 			mutex_unlock(&phone->lock);
 			irq_spinlock_unlock(&box->lock, true);
 
-			// FIXME: phone can become deallocated at any time now
-
 			/*
-			 * Send one message to the answerbox for each
-			 * phone. Used to make sure the kbox thread
-			 * wakes up after the last phone has been
-			 * disconnected.
+			 * Send one call to the answerbox for each phone.
+			 * Used to make sure the kbox thread wakes up after
+			 * the last phone has been disconnected. The call is
+			 * forgotten upon sending, so the "caller" may cease
+			 * to exist as soon as we release it.
 			 */
+			call_t *call = ipc_call_alloc(0);
 			IPC_SET_IMETHOD(call->data, IPC_M_PHONE_HUNGUP);
 			call->request_method = IPC_M_PHONE_HUNGUP;
 			call->flags |= IPC_CALL_DISCARD_ANSWER;
-			_ipc_call(phone, box, call);
-			
-			/* Allocate another call in advance */
-			call = ipc_call_alloc(0);
+			_ipc_call(phone, box, call, true);
+
+			task_release(phone->caller);
 			
 			/* Must start again */
@@ -659,8 +664,4 @@
 	
 	irq_spinlock_unlock(&box->lock, true);
-	
-	/* Free unused call */
-	if (call)
-		ipc_call_free(call);
 }
 
