diff --git a/base-linux/include/base/native_types.h b/base-linux/include/base/native_types.h index a91e4ecbe..39c141bc7 100644 --- a/base-linux/include/base/native_types.h +++ b/base-linux/include/base/native_types.h @@ -74,7 +74,7 @@ namespace Genode { */ struct Native_thread : Native_thread_id { - int socket; /* server-entrypoint socket */ + bool is_ipc_server; /** * Opaque pointer to additional thread-specific meta data @@ -85,7 +85,7 @@ namespace Genode { */ Thread_meta_data *meta_data; - Native_thread() : socket(-1), meta_data(0) { } + Native_thread() : is_ipc_server(false), meta_data(0) { } }; inline bool operator == (Native_thread_id t1, Native_thread_id t2) { diff --git a/base-linux/src/base/ipc/ipc.cc b/base-linux/src/base/ipc/ipc.cc index 150d50fc2..098c7af46 100644 --- a/base-linux/src/base/ipc/ipc.cc +++ b/base-linux/src/base/ipc/ipc.cc @@ -203,10 +203,33 @@ void Ipc_server::_reply_wait() Ipc_server::Ipc_server(Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg) -: Ipc_istream(rcv_msg), - Ipc_ostream(Native_capability(), snd_msg), _reply_needed(false) +: + Ipc_istream(rcv_msg), + Ipc_ostream(Native_capability(), snd_msg), _reply_needed(false) { + Thread_base *thread = Thread_base::myself(); + + /* + * If 'thread' is 0, the constructor was called by the main thread. By + * definition, main is never an RPC entrypoint. However, the main thread + * may call 'sleep_forever()', which instantiates 'Ipc_server'. + */ + + if (thread && thread->tid().is_ipc_server) { + PRAW("unexpected multiple instantiation of Ipc_server by one thread"); + struct Ipc_server_multiple_instance { }; + throw Ipc_server_multiple_instance(); + } + _rcv_cs = lx_server_socket(Thread_base::myself()); + if (_rcv_cs < 0) { + PRAW("lx_server_socket failed (error %d)", _rcv_cs); + struct Ipc_socket_creation_failed { }; + throw Ipc_socket_creation_failed(); + } + + if (thread) + thread->tid().is_ipc_server = true; _prepare_next_reply_wait(); } diff --git a/base-linux/src/platform/linux_socket.h b/base-linux/src/platform/linux_socket.h index 9d527cd12..5dafb9aee 100644 --- a/base-linux/src/platform/linux_socket.h +++ b/base-linux/src/platform/linux_socket.h @@ -3,13 +3,8 @@ * \author Christian Helmuth * \date 2012-01-17 * - * We create two sockets under lx_rpath() for each thread: client and server - * role. The naming is 'ep--'. The socket descriptors are - * cached in Thread_base::_tid. - * - * Currently two socket files are needed, as the client does not send the reply - * socket access-rights in a combined message with the payload. In the future, - * only server sockets must be bound in lx_rpath(). + * We create one socket under lx_rpath() for each 'Ipc_server'. The naming is + * 'ep--'. */ /* @@ -146,29 +141,28 @@ namespace { */ static int lx_server_socket(Genode::Thread_base *thread) { + int sd = lx_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (sd < 0) + return sd; + /* - * Main thread uses Ipc_server for sleep_forever() only. + * Main thread uses 'Ipc_server' for 'sleep_forever()' only. No need + * for binding. */ if (!thread) - return lx_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); + return sd; - if (thread->tid().socket == -1) { - int sd = lx_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (sd < 0) return -1; + sockaddr_un addr; + lx_create_server_addr(&addr, thread->tid().tid); - sockaddr_un addr; - lx_create_server_addr(&addr, thread->tid().tid); + /* make sure bind succeeds */ + lx_unlink(addr.sun_path); - /* make sure bind succeeds */ - lx_unlink(addr.sun_path); + int const bind_ret = lx_bind(sd, (sockaddr *)&addr, sizeof(addr)); + if (bind_ret < 0) + return bind_ret; - if (lx_bind(sd, (sockaddr *)&addr, sizeof(addr)) < 0) - return -2; - - thread->tid().socket = sd; - } - - return thread->tid().socket; + return sd; }