Support for socket-descriptor marshalling

This patch adds prinicipal support for transmitting socket descriptors
as RPC payload. Socket descriptors are handled by the linux-specific
implementation of the capability marshalling and unmarshalling functions
in 'ipc.h'. The 'Message' type in 'src/platform/linux_socket.h' has been
extended to carry multiple descriptors in a single message.

Unfortuately, we hit a problem (and potential show stopper) here:

  lx_sendmsg failed with -109 in lx_call()

The error code corresponds to ETOOMANYREFS. There is only one place in
the Linux kernel where this error code is used (net/unix/af_unix.c).
The code for 'unix_attach_fds()' suggests that there is a limit with
regard to the maximum number of references for a given Unix domain
socket. When the error occurs, core and init are running. The socket
of core's server entrypoint is present in the '/proc/pid/fd' of those
processes 8 times. The error occurs when core tries to perform an
RPC to the entrypoint to perform 'Ram_session::transfer_quota()'
(base/include/base/child.h at line 248).
This commit is contained in:
Norman Feske
2012-07-26 20:29:45 +02:00
parent 8b343d7e1a
commit ca4f574f4c
5 changed files with 270 additions and 60 deletions

View File

@ -92,9 +92,10 @@ void Ipc_istream::_wait()
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
: Ipc_unmarshaller(rcv_msg->buf, rcv_msg->size()),
Native_capability(Dst(lx_gettid(), -1), 0),
_rcv_msg(rcv_msg)
:
Ipc_unmarshaller(rcv_msg->buf, rcv_msg->size()),
Native_capability(Dst(lx_gettid(), -1), 0),
_rcv_msg(rcv_msg)
{ }
@ -115,15 +116,16 @@ void Ipc_client::_prepare_next_call()
/* prepare response buffer */
_read_offset = sizeof(long);
_snd_msg->reset_caps();
}
void Ipc_client::_call()
{
if (Ipc_ostream::_dst.valid()) {
lx_call(Ipc_ostream::_dst.dst().tid,
_snd_msg->buf, _write_offset,
_rcv_msg->buf, _rcv_msg->size());
_snd_msg->used_size(_write_offset);
lx_call(Ipc_ostream::_dst.dst().tid, *_snd_msg, *_rcv_msg);
}
_prepare_next_call();
}
@ -153,6 +155,9 @@ void Ipc_server::_prepare_next_reply_wait()
/* leave space for exc code at the beginning of the msgbuf */
_write_offset += align_natural(sizeof(int));
/* reset capability slots of send message buffer */
_snd_msg->reset_caps();
}
@ -161,7 +166,7 @@ void Ipc_server::_wait()
_reply_needed = true;
try {
int const reply_socket = lx_wait(_rcv_cs, _rcv_msg->buf, _rcv_msg->size());
int const reply_socket = lx_wait(_rcv_cs, *_rcv_msg);
/*
* Remember reply capability
@ -185,7 +190,8 @@ void Ipc_server::_wait()
void Ipc_server::_reply()
{
try {
lx_reply(Ipc_ostream::_dst.dst().socket, _snd_msg->buf, _write_offset);
_snd_msg->used_size(_write_offset);
lx_reply(Ipc_ostream::_dst.dst().socket, *_snd_msg);
} catch (Ipc_error) { }
_prepare_next_reply_wait();
@ -195,8 +201,10 @@ void Ipc_server::_reply()
void Ipc_server::_reply_wait()
{
/* when first called, there was no request yet */
if (_reply_needed)
lx_reply(Ipc_ostream::_dst.dst().socket, _snd_msg->buf, _write_offset);
if (_reply_needed) {
_snd_msg->used_size(_write_offset);
lx_reply(Ipc_ostream::_dst.dst().socket, *_snd_msg);
}
_wait();
}
@ -231,5 +239,9 @@ Ipc_server::Ipc_server(Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
if (thread)
thread->tid().is_ipc_server = true;
/* override capability initialization performed by 'Ipc_istream' */
*static_cast<Native_capability *>(this) =
Native_capability(Native_capability::Dst(lx_gettid(), _rcv_cs), 0);
_prepare_next_reply_wait();
}