From 363e0cdf698783119ca93328c1dbc599bd8a2696 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Thu, 3 Aug 2023 17:04:55 -0400 Subject: [PATCH] kernel/fd: deselect_select_infos must be called with io_mutex held. When the select/deselect API consumers invoke deselect(), they expect that when this function returns, no further references to the select_infos will remain and they can be safely deleted. In order for that to be true, we cannot remove the select_infos from the list in one step and deselect them in another; we must do both without releasing the lock in the middle. Should hopefully fix a rare KDL seen while testing .NET and the new event_queue. --- src/system/kernel/fs/fd.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/system/kernel/fs/fd.cpp b/src/system/kernel/fs/fd.cpp index 90dd22ff2c..c026fb4c28 100644 --- a/src/system/kernel/fs/fd.cpp +++ b/src/system/kernel/fs/fd.cpp @@ -374,11 +374,11 @@ remove_fd(struct io_context* context, int fd) disconnected = (descriptor->open_mode & O_DISCONNECTED); } - mutex_unlock(&context->io_mutex); - if (selectInfos != NULL) deselect_select_infos(descriptor, selectInfos, true); + mutex_unlock(&context->io_mutex); + return disconnected ? NULL : descriptor; } @@ -446,13 +446,12 @@ dup2_fd(int oldfd, int newfd, bool kernel) // Check for identity, note that it cannot be made above // because we always want to return an error on invalid // handles - select_info* selectInfos = NULL; if (oldfd != newfd) { // Now do the work TFD(Dup2FD(context, oldfd, newfd)); evicted = context->fds[newfd]; - selectInfos = context->select_infos[newfd]; + select_info* selectInfos = context->select_infos[newfd]; context->select_infos[newfd] = NULL; atomic_add(&context->fds[oldfd]->ref_count, 1); atomic_add(&context->fds[oldfd]->open_count, 1); @@ -460,6 +459,8 @@ dup2_fd(int oldfd, int newfd, bool kernel) if (evicted == NULL) context->num_used_fds++; + + deselect_select_infos(evicted, selectInfos, true); } fd_set_close_on_exec(context, newfd, false); @@ -468,7 +469,6 @@ dup2_fd(int oldfd, int newfd, bool kernel) // Say bye bye to the evicted fd if (evicted) { - deselect_select_infos(evicted, selectInfos, true); close_fd(context, evicted); put_fd(evicted); }