Skip to content

Commit

Permalink
fix(monika): _kern_close double close
Browse files Browse the repository at this point in the history
Fixed a bug when `_kern_close` translates into two host `close`
syscalls when the file descriptor refers to a directory.

This bug appear harmless for single-threaded programs but affects
programs like `launch_daemon` which opens a directory on both the
launcher thread and the main worker thread. The data race of one
thread closing a fd a second time right after the other thread
opening a new fd makes those programs think that there was
actually an error with the new fd.

After this fix `launch_daemon` should reliably launch on
`hyclone_server` startup. There should be no more
"id: cannot find name for user ID 0" errors on HyClone.
  • Loading branch information
trungnt2910 committed Apr 20, 2023
1 parent 40c7939 commit 00d7f7f
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 9 deletions.
2 changes: 1 addition & 1 deletion haiku_loader/loader_readdir.h
Expand Up @@ -9,7 +9,7 @@
// a directory fd may cause directory entries to be left behind.

void loader_opendir(int fd);
void loader_closedir(int fd);
bool loader_closedir(int fd);
int loader_readdir(int fd, void* buffer, size_t bufferSize, int maxCount);
void loader_rewinddir(int fd);
void loader_dupdir(int oldFd, int newFd);
Expand Down
4 changes: 2 additions & 2 deletions haiku_loader/sys/linux/loader_readdir.cpp
Expand Up @@ -67,10 +67,10 @@ void loader_opendir(int fd)
loader_opendir_unlocked(fd);
}

void loader_closedir(int fd)
bool loader_closedir(int fd)
{
std::unique_lock<std::mutex> lock(sFdMapMutex);
sFdMap.erase(fd);
return sFdMap.erase(fd);
}

void loader_dupdir(int oldFd, int newFd)
Expand Down
12 changes: 7 additions & 5 deletions monika/linux/io.cpp
Expand Up @@ -548,14 +548,16 @@ int _moni_close(int fd)
return HAIKU_POSIX_EBADF;
}

int result = LINUX_SYSCALL1(__NR_close, fd);

if (result < 0)
if (!GET_HOSTCALLS()->closedir(fd))
{
return LinuxToB(-result);
int result = LINUX_SYSCALL1(__NR_close, fd);

if (result < 0)
{
return LinuxToB(-result);
}
}

GET_HOSTCALLS()->closedir(fd);
GET_SERVERCALLS()->unregister_fd(fd);

return B_OK;
Expand Down
2 changes: 1 addition & 1 deletion shared_headers/extended_commpage.h
Expand Up @@ -85,7 +85,7 @@ struct hostcalls

// Readdir
void (*opendir)(int fd);
void (*closedir)(int fd);
bool (*closedir)(int fd);
int (*readdir)(int fd, void* buffer, size_t bufferSize, int maxCount);
void (*rewinddir)(int fd);
void (*dupdir)(int oldFd, int newFd);
Expand Down

0 comments on commit 00d7f7f

Please sign in to comment.