mirror of
https://github.com/genodelabs/genode.git
synced 2025-05-31 22:50:54 +00:00
libc: fix nested monitor call in 'symlink'
The symlink implementation wrongly constructed a 'Sync' object within the context of a monitor call. The 'Sync' constructor indirectly depended on libc I/O for obtaining the current time, ultimately resulting in a nested attempt of a monitor call. This could be reproduced via the base.run script: $ cd /home $ ln -s a b The 'ln' command resulted in the following log message: [init -> /bin/bash -> 7] Error: deadlock ahead, mutex=0x10ff8c70, return ip=0x500583a7 The patch fixes the problem by splitting the single monitor call into two monitor calls and moving the construction of the 'Sync' object in-between both monitor calls, thereby executing the constructor at the libc application level. Fixes #4219
This commit is contained in:
parent
f3908b8283
commit
5138aeba80
@ -1675,22 +1675,16 @@ int Libc::Vfs_plugin::fsync(File_descriptor *fd)
|
||||
|
||||
int Libc::Vfs_plugin::symlink(const char *target_path, const char *link_path)
|
||||
{
|
||||
enum class Stage { OPEN, WRITE, SYNC };
|
||||
|
||||
Stage stage { Stage::OPEN };
|
||||
Vfs::Vfs_handle *handle { nullptr };
|
||||
Constructible<Sync> sync;
|
||||
Vfs::file_size const count { ::strlen(target_path) + 1 };
|
||||
Vfs::file_size out_count { 0 };
|
||||
|
||||
|
||||
{
|
||||
bool succeeded { false };
|
||||
int result_errno { 0 };
|
||||
monitor().monitor([&] {
|
||||
|
||||
switch (stage) {
|
||||
case Stage::OPEN:
|
||||
{
|
||||
typedef Vfs::Directory_service::Openlink_result Openlink_result;
|
||||
|
||||
Openlink_result openlink_result =
|
||||
@ -1716,8 +1710,25 @@ int Libc::Vfs_plugin::symlink(const char *target_path, const char *link_path)
|
||||
}
|
||||
|
||||
handle->handler(&_response_handler);
|
||||
succeeded = true;
|
||||
return Fn::COMPLETE;
|
||||
});
|
||||
|
||||
if (!succeeded)
|
||||
return Errno(result_errno);
|
||||
}
|
||||
|
||||
/* must be done outside the monitor because constructor needs libc I/O */
|
||||
sync.construct(*handle, _update_mtime, _current_real_time);
|
||||
} stage = Stage::WRITE; [[fallthrough]];
|
||||
|
||||
{
|
||||
bool succeeded { false };
|
||||
int result_errno { 0 };
|
||||
enum class Stage { WRITE, SYNC } stage = Stage::WRITE;
|
||||
|
||||
monitor().monitor([&] {
|
||||
|
||||
switch (stage) {
|
||||
|
||||
case Stage::WRITE:
|
||||
{
|
||||
@ -1745,6 +1756,7 @@ int Libc::Vfs_plugin::symlink(const char *target_path, const char *link_path)
|
||||
|
||||
if (!succeeded)
|
||||
return Errno(result_errno);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user