From d4e0d2f578932a7c0a0c71bcddbba0b5501fa7ff Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Sun, 3 Nov 2019 11:53:13 +0100 Subject: [PATCH] libc: defer clone ack after FD initialization Issue #3478 Issue #2303 --- repos/libports/src/lib/libc/internal/kernel.h | 2 ++ repos/libports/src/lib/libc/kernel.cc | 28 +++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/repos/libports/src/lib/libc/internal/kernel.h b/repos/libports/src/lib/libc/internal/kernel.h index 57dcaf293..e5edab542 100644 --- a/repos/libports/src/lib/libc/internal/kernel.h +++ b/repos/libports/src/lib/libc/internal/kernel.h @@ -211,6 +211,8 @@ struct Libc::Kernel final : Vfs::Io_response_handler, Pthread_pool _pthreads { _timer_accessor }; + Constructible _clone_connection { }; + struct Resumer { GENODE_RPC(Rpc_resume, void, resume); diff --git a/repos/libports/src/lib/libc/kernel.cc b/repos/libports/src/lib/libc/kernel.cc index ad32a5ba2..892614bd2 100644 --- a/repos/libports/src/lib/libc/kernel.cc +++ b/repos/libports/src/lib/libc/kernel.cc @@ -109,6 +109,9 @@ void Libc::Kernel::_init_file_descriptors() return; File_descriptor *fd = _vfs.open(path.string(), flags, libc_fd); + if (!fd) + return; + if (fd->libc_fd != libc_fd) { error("could not allocate fd ",libc_fd," for ",path,", " "got fd ",fd->libc_fd); @@ -251,21 +254,21 @@ void Libc::Kernel::_clone_state_from_parent() _env.ram(), _env.rm(), range.at, range.size); }); - Clone_connection clone_connection(_env); + _clone_connection.construct(_env); /* fetch heap content */ _cloned_heap_ranges.for_each([&] (Cloned_malloc_heap_range &heap_range) { - heap_range.import_content(clone_connection); }); + heap_range.import_content(*_clone_connection); }); /* fetch user contex of the parent's application */ - clone_connection.memory_content(&_user_context, sizeof(_user_context)); + _clone_connection->memory_content(&_user_context, sizeof(_user_context)); _valid_user_context = true; _libc_env.libc_config().for_each_sub_node([&] (Xml_node node) { auto copy_from_parent = [&] (Range range) { - clone_connection.memory_content(range.at, range.size); + _clone_connection->memory_content(range.at, range.size); }; /* clone application stack */ @@ -292,8 +295,8 @@ void Libc::Kernel::_clone_state_from_parent() }); /* import application-heap state from parent */ - clone_connection.object_content(_malloc_heap); - init_malloc_cloned(clone_connection); + _clone_connection->object_content(_malloc_heap); + init_malloc_cloned(*_clone_connection); } @@ -384,4 +387,17 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap) _init_file_descriptors(); _kernel_ptr = this; + + /* + * Acknowledge the completion of 'fork' to the parent + * + * This must be done after '_init_file_descriptors' to ensure that pipe FDs + * of the parent are opened at the child before the parent continues. + * Otherwise, the parent would potentially proceed with closing the pipe + * FDs before the child has a chance to open them. In this situation, the + * pipe reference counter may reach an intermediate value of zero, + * triggering the destruction of the pipe. + */ + if (_cloned) + _clone_connection.destruct(); }