Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 4e739652767ec6bc58f3d27c494e3eb35f6aaa88)
+++ kernel/generic/include/ipc/ipc.h	(revision de9460ef8f1f8310420d8ef918f7b9b76d0ae4f7)
@@ -51,14 +51,12 @@
 /** This is answer to a call */
 #define IPC_CALL_ANSWERED	(1 << 0)
-/** This call will not be freed on error */
-#define IPC_CALL_STATIC_ALLOC	(1 << 1)
 /** Answer will not be passed to userspace, will be discarded */
-#define IPC_CALL_DISCARD_ANSWER	(1 << 2)
+#define IPC_CALL_DISCARD_ANSWER (1 << 1)
 /** Call was forwarded */
-#define IPC_CALL_FORWARDED	(1 << 3)
+#define IPC_CALL_FORWARDED	(1 << 2)
 /** Identify connect_me_to answer */
-#define IPC_CALL_CONN_ME_TO	(1 << 4)
+#define IPC_CALL_CONN_ME_TO	(1 << 3)
 /** Interrupt notification */
-#define IPC_CALL_NOTIF		(1 << 5)
+#define IPC_CALL_NOTIF		(1 << 4)
 
 /*
@@ -267,4 +265,7 @@
 	waitq_t wq;
 
+	/** Linkage for the list of task's synchronous answerboxes. */
+	link_t sync_box_link;
+
 	/** Phones connected to this answerbox. */
 	link_t connected_phones;
@@ -316,25 +317,31 @@
 } call_t;
 
+
+extern answerbox_t *ipc_phone_0;
+
+
 extern void ipc_init(void);
-extern call_t * ipc_wait_for_call(answerbox_t *, uint32_t, int);
-extern void ipc_answer(answerbox_t *, call_t *);
+
+extern call_t * ipc_call_alloc(int);
+extern void ipc_call_free(call_t *);
+
 extern int ipc_call(phone_t *, call_t *);
 extern int ipc_call_sync(phone_t *, call_t *);
+extern call_t * ipc_wait_for_call(answerbox_t *, uint32_t, int);
+extern int ipc_forward(call_t *, phone_t *, answerbox_t *, int);
+extern void ipc_answer(answerbox_t *, call_t *);
+
 extern void ipc_phone_init(phone_t *);
 extern void ipc_phone_connect(phone_t *, answerbox_t *);
-extern void ipc_call_free(call_t *);
-extern call_t * ipc_call_alloc(int);
+extern int ipc_phone_hangup(phone_t *);
+
 extern void ipc_answerbox_init(answerbox_t *, struct task *);
-extern void ipc_call_static_init(call_t *);
-extern void task_print_list(void);
-extern int ipc_forward(call_t *, phone_t *, answerbox_t *, int);
+
 extern void ipc_cleanup(void);
-extern int ipc_phone_hangup(phone_t *);
 extern void ipc_backsend_err(phone_t *, call_t *, unative_t);
-extern void ipc_print_task(task_id_t);
 extern void ipc_answerbox_slam_phones(answerbox_t *, bool);
 extern void ipc_cleanup_call_list(link_t *);
 
-extern answerbox_t *ipc_phone_0;
+extern void ipc_print_task(task_id_t);
 
 #endif
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision 4e739652767ec6bc58f3d27c494e3eb35f6aaa88)
+++ kernel/generic/include/proc/task.h	(revision de9460ef8f1f8310420d8ef918f7b9b76d0ae4f7)
@@ -98,4 +98,6 @@
 	 */
 	atomic_t active_calls;
+	/** List of synchronous answerboxes. */
+	link_t sync_box_head;
 
 #ifdef CONFIG_UDEBUG
@@ -132,4 +134,5 @@
 extern int task_kill(task_id_t id);
 extern uint64_t task_get_accounting(task_t *t);
+extern void task_print_list(void);
 
 extern void cap_set(task_t *t, cap_t caps);
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 4e739652767ec6bc58f3d27c494e3eb35f6aaa88)
+++ kernel/generic/src/ipc/ipc.c	(revision de9460ef8f1f8310420d8ef918f7b9b76d0ae4f7)
@@ -62,4 +62,5 @@
 
 static slab_cache_t *ipc_call_slab;
+static slab_cache_t *ipc_answerbox_slab;
 
 /** Initialize a call structure.
@@ -96,15 +97,4 @@
 }
 
-/** Initialize a statically allocated call structure.
- *
- * @param call		Statically allocated kernel call structure to be
- *			initialized.
- */
-void ipc_call_static_init(call_t *call)
-{
-	_ipc_call_init(call);
-	call->flags |= IPC_CALL_STATIC_ALLOC;
-}
-
 /** Deallocate a call structure.
  *
@@ -113,5 +103,4 @@
 void ipc_call_free(call_t *call)
 {
-	ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
 	/* Check to see if we have data in the IPC_M_DATA_SEND buffer. */
 	if (call->buffer)
@@ -130,4 +119,5 @@
 	spinlock_initialize(&box->irq_lock, "ipc_box_irqlock");
 	waitq_initialize(&box->wq);
+	link_initialize(&box->sync_box_link);
 	list_initialize(&box->connected_phones);
 	list_initialize(&box->calls);
@@ -179,15 +169,41 @@
 int ipc_call_sync(phone_t *phone, call_t *request)
 {
-	answerbox_t sync_box; 
-
-	ipc_answerbox_init(&sync_box, TASK);
+	answerbox_t *sync_box; 
+	ipl_t ipl;
+
+	sync_box = slab_alloc(ipc_answerbox_slab, 0);
+	ipc_answerbox_init(sync_box, TASK);
+
+	/*
+	 * Put the answerbox on the TASK's list of synchronous answerboxes so
+	 * that it can be cleaned up if the call is interrupted.
+	 */
+	ipl = interrupts_disable();
+	spinlock_lock(&TASK->lock);
+	list_append(&sync_box->sync_box_link, &TASK->sync_box_head);
+	spinlock_unlock(&TASK->lock);
+	interrupts_restore(ipl);
 
 	/* We will receive data in a special box. */
-	request->callerbox = &sync_box;
+	request->callerbox = sync_box;
 
 	ipc_call(phone, request);
-	if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT,
-	    SYNCH_FLAGS_INTERRUPTIBLE))
+	if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT,
+	    SYNCH_FLAGS_INTERRUPTIBLE)) {
+	    	/* The answerbox and the call will be freed by ipc_cleanup(). */
 		return EINTR;
+	}
+
+	/*
+	 * The answer arrived without interruption so we can remove the
+	 * answerbox from the TASK's list of synchronous answerboxes.
+	 */
+	(void) interrupts_disable();
+	spinlock_lock(&TASK->lock);
+	list_remove(&sync_box->sync_box_link);
+	spinlock_unlock(&TASK->lock);
+	interrupts_restore(ipl);
+
+	slab_free(ipc_answerbox_slab, sync_box);
 	return EOK;
 }
@@ -520,4 +536,5 @@
 	int i;
 	call_t *call;
+	ipl_t ipl;
 
 	/* Disconnect all our phones ('ipc_phone_hangup') */
@@ -545,5 +562,19 @@
 	spinlock_unlock(&TASK->answerbox.lock);
 	
-	/* Wait for all async answers to arrive */
+	/* Wait for all answers to interrupted synchronous calls to arrive */
+	ipl = interrupts_disable();
+	while (!list_empty(&TASK->sync_box_head)) {
+		answerbox_t *box = list_get_instance(TASK->sync_box_head.next,
+		    answerbox_t, sync_box_link);
+
+		list_remove(&box->sync_box_link);
+		call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,
+		    SYNCH_FLAGS_NONE);
+		ipc_call_free(call);
+		slab_free(ipc_answerbox_slab, box);
+	}
+	interrupts_restore(ipl);
+
+	/* Wait for all answers to asynchronous calls to arrive */
 	while (1) {
 		/* Go through all phones, until all are FREE... */
@@ -574,5 +605,4 @@
 		ASSERT((call->flags & IPC_CALL_ANSWERED) ||
 		    (call->flags & IPC_CALL_NOTIF));
-		ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
 		
 		/*
@@ -593,4 +623,6 @@
 	ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL,
 	    NULL, 0);
+	ipc_answerbox_slab = slab_cache_create("ipc_answerbox",
+	    sizeof(answerbox_t), 0, NULL, NULL, 0);
 }
 
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 4e739652767ec6bc58f3d27c494e3eb35f6aaa88)
+++ kernel/generic/src/ipc/sysipc.c	(revision de9460ef8f1f8310420d8ef918f7b9b76d0ae4f7)
@@ -531,5 +531,5 @@
     unative_t arg1, unative_t arg2, unative_t arg3, ipc_data_t *data)
 {
-	call_t call;
+	call_t *call;
 	phone_t *phone;
 	int res;
@@ -538,32 +538,35 @@
 	GET_CHECK_PHONE(phone, phoneid, return ENOENT);
 
-	ipc_call_static_init(&call);
-	IPC_SET_METHOD(call.data, method);
-	IPC_SET_ARG1(call.data, arg1);
-	IPC_SET_ARG2(call.data, arg2);
-	IPC_SET_ARG3(call.data, arg3);
+	call = ipc_call_alloc(0);
+	IPC_SET_METHOD(call->data, method);
+	IPC_SET_ARG1(call->data, arg1);
+	IPC_SET_ARG2(call->data, arg2);
+	IPC_SET_ARG3(call->data, arg3);
 	/*
 	 * To achieve deterministic behavior, zero out arguments that are beyond
 	 * the limits of the fast version.
 	 */
-	IPC_SET_ARG4(call.data, 0);
-	IPC_SET_ARG5(call.data, 0);
-
-	if (!(res = request_preprocess(&call, phone))) {
+	IPC_SET_ARG4(call->data, 0);
+	IPC_SET_ARG5(call->data, 0);
+
+	if (!(res = request_preprocess(call, phone))) {
 #ifdef CONFIG_UDEBUG
 		udebug_stoppable_begin();
 #endif
-		rc = ipc_call_sync(phone, &call);
+		rc = ipc_call_sync(phone, call);
 #ifdef CONFIG_UDEBUG
 		udebug_stoppable_end();
 #endif
-		if (rc != EOK)
+		if (rc != EOK) {
+			/* The call will be freed by ipc_cleanup(). */
 			return rc;
-		process_answer(&call);
+		}
+		process_answer(call);
 
 	} else {
-		IPC_SET_RETVAL(call.data, res);
-	}
-	rc = STRUCT_TO_USPACE(&data->args, &call.data.args);
+		IPC_SET_RETVAL(call->data, res);
+	}
+	rc = STRUCT_TO_USPACE(&data->args, &call->data.args);
+	ipc_call_free(call);
 	if (rc != 0)
 		return rc;
@@ -584,32 +587,38 @@
     ipc_data_t *reply)
 {
-	call_t call;
+	call_t *call;
 	phone_t *phone;
 	int res;
 	int rc;
 
-	ipc_call_static_init(&call);
-	rc = copy_from_uspace(&call.data.args, &question->args,
-	    sizeof(call.data.args));
-	if (rc != 0)
+	GET_CHECK_PHONE(phone, phoneid, return ENOENT);
+
+	call = ipc_call_alloc(0);
+	rc = copy_from_uspace(&call->data.args, &question->args,
+	    sizeof(call->data.args));
+	if (rc != 0) {
+		ipc_call_free(call);
 		return (unative_t) rc;
-
-	GET_CHECK_PHONE(phone, phoneid, return ENOENT);
-
-	if (!(res = request_preprocess(&call, phone))) {
+	}
+
+
+	if (!(res = request_preprocess(call, phone))) {
 #ifdef CONFIG_UDEBUG
 		udebug_stoppable_begin();
 #endif
-		rc = ipc_call_sync(phone, &call);
+		rc = ipc_call_sync(phone, call);
 #ifdef CONFIG_UDEBUG
 		udebug_stoppable_end();
 #endif
-		if (rc != EOK)
+		if (rc != EOK) {
+			/* The call will be freed by ipc_cleanup(). */
 			return rc;
-		process_answer(&call);
+		}
+		process_answer(call);
 	} else 
-		IPC_SET_RETVAL(call.data, res);
-
-	rc = STRUCT_TO_USPACE(&reply->args, &call.data.args);
+		IPC_SET_RETVAL(call->data, res);
+
+	rc = STRUCT_TO_USPACE(&reply->args, &call->data.args);
+	ipc_call_free(call);
 	if (rc != 0)
 		return rc;
@@ -991,6 +1000,4 @@
 
 	if (call->flags & IPC_CALL_NOTIF) {
-		ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
-
 		/* Set in_phone_hash to the interrupt counter */
 		call->data.phone = (void *) call->priv;
@@ -1005,6 +1012,4 @@
 	if (call->flags & IPC_CALL_ANSWERED) {
 		process_answer(call);
-
-		ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
 
 		if (call->flags & IPC_CALL_DISCARD_ANSWER) {
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 4e739652767ec6bc58f3d27c494e3eb35f6aaa88)
+++ kernel/generic/src/proc/task.c	(revision de9460ef8f1f8310420d8ef918f7b9b76d0ae4f7)
@@ -178,4 +178,5 @@
 		ipc_phone_connect(&ta->phones[0], ipc_phone_0);
 	atomic_set(&ta->active_calls, 0);
+	list_initialize(&ta->sync_box_head);
 
 	mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE);
