nova: ease debugging if no cap indexes are left

If we ran out of capabilities indexes, the bit allocator throws an exception.
If this happens the code seems to hang and nothing happens.

Instead one could catch the exception and print some diagnostic message.
This would be nice, but don't work. Printing some diagnostic message itself
tries to do potentially IPC and will allocate new capability indexes at
least for the receive window.

So, catch the exception and let the thread die, so at least the instruction
pointer is left as trace to identify the reason of the trouble.

Fixes #625
This commit is contained in:
Alexander Boettcher 2013-01-17 17:09:09 +01:00 committed by Norman Feske
parent e817163f1a
commit 486b27a1b8
3 changed files with 55 additions and 43 deletions

View File

@ -54,7 +54,7 @@ namespace Genode {
struct {
addr_t sel;
unsigned rights;
bool trans_map;
bool trans_map;
} _snd_pt_sel [MAX_CAP_ARGS];
/**
@ -280,32 +280,43 @@ namespace Genode {
* rcv_window parameter, this function allocates a
* fresh receive window and clears 'rcv_invalid'.
*/
void rcv_prepare_pt_sel_window(Nova::Utcb *utcb,
bool rcv_prepare_pt_sel_window(Nova::Utcb *utcb,
addr_t rcv_window = INVALID_INDEX)
{
/*
* If a rcv_window was specified use solely
* the selector specified by rcv_window.
*/
if (rcv_window != INVALID_INDEX) {
/* cleanup if this msgbuf was already used */
if (!rcv_invalid()) rcv_cleanup(false);
try {
/*
* If a rcv_window was specified use solely
* the selector specified by rcv_window.
*/
if (rcv_window != INVALID_INDEX) {
/* cleanup if this msgbuf was already used */
if (!rcv_invalid()) rcv_cleanup(false);
_rcv_pt_base = rcv_window;
} else {
if (rcv_invalid() || rcv_cleanup(true))
_rcv_pt_base = cap_selector_allocator()->alloc(MAX_CAP_ARGS_LOG2);
_rcv_pt_base = rcv_window;
} else {
if (rcv_invalid() || rcv_cleanup(true))
_rcv_pt_base = cap_selector_allocator()->alloc(MAX_CAP_ARGS_LOG2);
}
addr_t max = 0;
if (rcv_window == INVALID_INDEX)
max = MAX_CAP_ARGS_LOG2;
using namespace Nova;
/* setup receive window */
utcb->crd_rcv = Obj_crd(rcv_pt_base(), max);
/* open maximal translate window */
utcb->crd_xlt = Obj_crd(0, ~0UL);
return true;
} catch (Bit_array_out_of_indexes) {
using namespace Nova;
/* setup receive window */
utcb->crd_rcv = Obj_crd();
/* open maximal translate window */
utcb->crd_xlt = Obj_crd(0, ~0UL);
return false;
}
addr_t max = 0;
if (rcv_window == INVALID_INDEX)
max = MAX_CAP_ARGS_LOG2;
using namespace Nova;
/* setup receive window */
utcb->crd_rcv = Obj_crd(rcv_pt_base(), max);
/* open maximal translate window */
utcb->crd_xlt = Obj_crd(0, ~0UL);
}
/**
@ -346,7 +357,7 @@ namespace Genode {
_rcv_pt_cap_free [cap.base() - rcv_pt_base()] = UNUSED_CAP;
}
if (_rcv_pt_sel_max >= max) continue;
if (_rcv_pt_sel_max >= max) continue;
/* track the order of mapped and translated items */
if (cap.is_null()) {
@ -368,7 +379,6 @@ namespace Genode {
if (max != MAX_CAP_ARGS)
_rcv_pt_base = INVALID_INDEX;
}
};

View File

@ -140,7 +140,11 @@ void Ipc_client::_call()
PERR("could not setup IPC");
return;
}
_rcv_msg->rcv_prepare_pt_sel_window(utcb, Ipc_ostream::_dst.rcv_window());
/* if we can't setup receive window, die in order to recognize the issue */
if (!_rcv_msg->rcv_prepare_pt_sel_window(utcb, Ipc_ostream::_dst.rcv_window()))
/* printf doesn't work here since for IPC also rcv_prepare* is used */
nova_die();
/* establish the mapping via a portal traversal */
uint8_t res = Nova::call(Ipc_ostream::_dst.local_name());

View File

@ -105,7 +105,7 @@ void Rpc_entrypoint::_activation_entry()
Ipc_server srv(&ep->_snd_buf, &ep->_rcv_buf);
ep->_rcv_buf.post_ipc(reinterpret_cast<Nova::Utcb *>(ep->utcb()));
/* destination of next reply */
/* destination of next reply - no effect on nova */
srv.dst(Native_capability(id_pt));
int opcode = 0;
@ -116,11 +116,7 @@ void Rpc_entrypoint::_activation_entry()
srv.ret(ERR_INVALID_OBJECT);
/* atomically lookup and lock referenced object */
Rpc_object_base * curr_obj = ep->lookup_and_lock(id_pt);
{
Lock::Guard lock_guard(ep->_curr_obj_lock);
ep->_curr_obj = curr_obj;
}
ep->_curr_obj = ep->lookup_and_lock(id_pt);
if (!ep->_curr_obj) {
/*
@ -133,21 +129,23 @@ void Rpc_entrypoint::_activation_entry()
" return from call id_pt=%lx",
id_pt);
srv << IPC_REPLY;
}
} else {
/* dispatch request */
try { srv.ret(ep->_curr_obj->dispatch(opcode, srv, srv)); }
catch (Blocking_canceled) { }
/* dispatch request */
try { srv.ret(ep->_curr_obj->dispatch(opcode, srv, srv)); }
catch (Blocking_canceled) { }
Rpc_object_base * tmp = ep->_curr_obj;
{
Lock::Guard lock_guard(ep->_curr_obj_lock);
Rpc_object_base * tmp = ep->_curr_obj;
ep->_curr_obj = 0;
}
tmp->release();
ep->_rcv_buf.rcv_prepare_pt_sel_window((Nova::Utcb *)ep->utcb());
tmp->release();
}
/* if we can't setup receive window, die in order to recognize the issue */
if (!ep->_rcv_buf.rcv_prepare_pt_sel_window((Nova::Utcb *)ep->utcb()))
/* printf doesn't work here since for IPC also rcv_prepare* is used */
nova_die();
srv << IPC_REPLY;
}