diff --git a/repos/ports/include/noux_session/sysio.h b/repos/ports/include/noux_session/sysio.h index cfa8f7008..5defa8f4e 100644 --- a/repos/ports/include/noux_session/sysio.h +++ b/repos/ports/include/noux_session/sysio.h @@ -155,7 +155,8 @@ struct Noux::Sysio enum Fcntl_cmd { FCNTL_CMD_GET_FILE_STATUS_FLAGS, FCNTL_CMD_SET_FILE_STATUS_FLAGS, - FCNTL_CMD_SET_FD_FLAGS + FCNTL_CMD_SET_FD_FLAGS, + FCNTL_CMD_GET_FD_FLAGS }; /** diff --git a/repos/ports/src/lib/libc_noux/plugin.cc b/repos/ports/src/lib/libc_noux/plugin.cc index a5b32a246..355357c67 100644 --- a/repos/ports/src/lib/libc_noux/plugin.cc +++ b/repos/ports/src/lib/libc_noux/plugin.cc @@ -1595,14 +1595,8 @@ namespace { } case F_GETFD: - /* - * Normally, we would return the file-descriptor flags. - * - * XXX: FD_CLOEXEC not yet supported - */ - if (verbose) - warning("fcntl(F_GETFD) not implemented, returning 0"); - return 0; + sysio()->fcntl_in.cmd = Noux::Sysio::FCNTL_CMD_GET_FD_FLAGS; + break; case F_SETFD: sysio()->fcntl_in.cmd = Noux::Sysio::FCNTL_CMD_SET_FD_FLAGS; diff --git a/repos/ports/src/noux/child.h b/repos/ports/src/noux/child.h index 5c024056f..719a17cdc 100644 --- a/repos/ports/src/noux/child.h +++ b/repos/ports/src/noux/child.h @@ -243,11 +243,15 @@ class Noux::Child : public Rpc_object, /** * Let specified child inherit our file descriptors */ - void _assign_io_channels_to(Child *child) + void _assign_io_channels_to(Child *child, bool skip_when_close_on_execve_set) { for (int fd = 0; fd < MAX_FILE_DESCRIPTORS; fd++) - if (fd_in_use(fd)) + if (fd_in_use(fd)) { + if (skip_when_close_on_execve_set && close_fd_on_execve(fd)) + continue; child->add_io_channel(io_channel_by_fd(fd), fd); + child->close_fd_on_execve(fd, close_fd_on_execve(fd)); + } } /** @@ -536,7 +540,7 @@ class Noux::Child : public Rpc_object, false, _destruct_queue); - _assign_io_channels_to(child); + _assign_io_channels_to(child, true); /* move the signal queue */ while (!_pending_signals.empty()) diff --git a/repos/ports/src/noux/file_descriptor_registry.h b/repos/ports/src/noux/file_descriptor_registry.h index b17529e3c..cb91fb757 100644 --- a/repos/ports/src/noux/file_descriptor_registry.h +++ b/repos/ports/src/noux/file_descriptor_registry.h @@ -30,6 +30,7 @@ class Noux::File_descriptor_registry struct { bool allocated; + bool close_on_execve; Shared_pointer io_channel; } _fds[MAX_FILE_DESCRIPTORS]; @@ -51,14 +52,16 @@ class Noux::File_descriptor_registry void _assign_fd(int fd, Shared_pointer &io_channel) { - _fds[fd].io_channel = io_channel; - _fds[fd].allocated = true; + _fds[fd].io_channel = io_channel; + _fds[fd].allocated = true; + _fds[fd].close_on_execve = false; } void _reset_fd(int fd) { - _fds[fd].io_channel = Shared_pointer(); - _fds[fd].allocated = false; + _fds[fd].io_channel = Shared_pointer(); + _fds[fd].allocated = false; + _fds[fd].close_on_execve = false; } public: @@ -110,6 +113,24 @@ class Noux::File_descriptor_registry return _fds[fd].io_channel; } + void close_fd_on_execve(int fd, bool close_on_execve) + { + if (!_valid_fd(fd)) + error("file descriptor ", fd, " is out of range"); + else + _fds[fd].close_on_execve = close_on_execve; + } + + bool close_fd_on_execve(int fd) + { + if (!_valid_fd(fd)) { + error("file descriptor ", fd, " is out of range"); + return false; + } + + return _fds[fd].close_on_execve; + } + virtual void flush() { /* close all file descriptors */ diff --git a/repos/ports/src/noux/io_channel.h b/repos/ports/src/noux/io_channel.h index f135212ff..eae726390 100644 --- a/repos/ports/src/noux/io_channel.h +++ b/repos/ports/src/noux/io_channel.h @@ -68,10 +68,6 @@ class Noux::Io_channel : public Reference_counter public: - bool close_on_execve; - - Io_channel() : close_on_execve(false) { } - virtual ~Io_channel() { } virtual Io_channel_backend *backend() { return nullptr; } diff --git a/repos/ports/src/noux/syscall.cc b/repos/ports/src/noux/syscall.cc index 822fd4016..369b4e932 100644 --- a/repos/ports/src/noux/syscall.cc +++ b/repos/ports/src/noux/syscall.cc @@ -171,8 +171,15 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) if (_sysio.fcntl_in.cmd == Sysio::FCNTL_CMD_SET_FD_FLAGS) { /* we assume that there is only the close-on-execve flag */ - _lookup_channel(_sysio.fcntl_in.fd)->close_on_execve = - !!_sysio.fcntl_in.long_arg; + close_fd_on_execve(_sysio.fcntl_in.fd, !!_sysio.fcntl_in.long_arg); + result = true; + break; + } + + if (_sysio.fcntl_in.cmd == Sysio::FCNTL_CMD_GET_FD_FLAGS) { + + /* we assume that there is only the close-on-execve flag */ + _sysio.fcntl_out.result = close_fd_on_execve(_sysio.fcntl_in.fd); result = true; break; } @@ -556,7 +563,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) Family_member::insert(child); - _assign_io_channels_to(child); + _assign_io_channels_to(child, false); /* copy our address space into the new child */ try {