From 45cb1a2f576988fd518fe8454e7347e7357b0857 Mon Sep 17 00:00:00 2001 From: Hongbo Zhang Date: Tue, 28 Oct 2025 15:52:16 +0800 Subject: [PATCH 1/4] filter `target` to make output more stable --- src/fs/dir_test.mbt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/fs/dir_test.mbt b/src/fs/dir_test.mbt index 06ac4082..8ee85bb9 100644 --- a/src/fs/dir_test.mbt +++ b/src/fs/dir_test.mbt @@ -16,7 +16,9 @@ async test "read_all" { let dir = @fs.opendir("src/fs") defer dir.close() - let list = dir.read_all() + let list = dir + .read_all() + .filter_map(x => if x is "target" { None } else { Some(x) }) list.sort() @json.inspect(list, content=[ "fs.mbt", "stub.c", "dir.mbt", "README.md", "utils.mbt", "dir_test.mbt", "eof_test.mbt", @@ -33,7 +35,9 @@ async test "as_dir" { guard dir_file.kind() is Directory let dir = dir_file.as_dir() defer dir.close() - let list = dir.read_all() + let list = dir + .read_all() + .filter_map(x => if x is "target" { None } else { Some(x) }) list.sort() let kinds = [] for file in list { From 09743938b17accac6e5ec61c66f3536374769505 Mon Sep 17 00:00:00 2001 From: Hongbo Zhang Date: Tue, 28 Oct 2025 15:56:02 +0800 Subject: [PATCH 2/4] add extra payload to make OSError more helpful when possible --- src/fs/access_test.mbt | 2 +- src/internal/event_loop/event_loop.mbt | 12 +++- src/internal/event_loop/fs.mbt | 69 +++++++++++++++++------ src/internal/event_loop/network.mbt | 7 ++- src/internal/event_loop/worker_wbtest.mbt | 3 +- src/os_error/error.mbt | 17 +++--- src/os_error/pkg.generated.mbti | 2 +- 7 files changed, 80 insertions(+), 32 deletions(-) diff --git a/src/fs/access_test.mbt b/src/fs/access_test.mbt index a971d205..a1cd12fb 100644 --- a/src/fs/access_test.mbt +++ b/src/fs/access_test.mbt @@ -23,7 +23,7 @@ async test "exists" { inspect( try? ignore(@fs.open("moon.mod.json.not_exist", mode=ReadOnly)), content=( - #|Err(OSError("@fs.open(): No such file or directory")) + #|Err(OSError("@fs.open(): No such file or directory", "moon.mod.json.not_exist")) ), ) } diff --git a/src/internal/event_loop/event_loop.mbt b/src/internal/event_loop/event_loop.mbt index f14496a1..642a8b2d 100644 --- a/src/internal/event_loop/event_loop.mbt +++ b/src/internal/event_loop/event_loop.mbt @@ -317,6 +317,7 @@ pub fn close_fd(fd : Int) -> Unit { async fn perform_job_in_worker( job : JobForWorker, context~ : String, + extra~ : StringView?, allow_cancel? : Bool = false, ) -> Int { guard curr_loop.val is Some(evloop) @@ -340,7 +341,11 @@ async fn perform_job_in_worker( @coroutine.protect_from_cancel(@coroutine.suspend) } if job.err() > 0 { - raise @os_error.OSError(job.err(), context~) + raise @os_error.OSError( + job.err(), + context~, + extra=extra.map(x => x.to_string()), + ) } else { job.ret() } @@ -380,7 +385,7 @@ pub async fn read( ret } else { let job = JobForWorker::read(fd, buf, offset, len) - perform_job_in_worker(job, context~) + perform_job_in_worker(job, context~, extra=None) } } @@ -418,7 +423,7 @@ pub async fn write( ret } else { let job = JobForWorker::write(fd, buf, offset, len) - perform_job_in_worker(job, context~) + perform_job_in_worker(job, context~, extra=None) } } @@ -436,6 +441,7 @@ pub async fn spawn( perform_job_in_worker( JobForWorker::spawn(path, args, env, stdin, stdout, stderr, cwd), context~, + extra=None, ) } diff --git a/src/internal/event_loop/fs.mbt b/src/internal/event_loop/fs.mbt index 5d5e3f11..76a33715 100644 --- a/src/internal/event_loop/fs.mbt +++ b/src/internal/event_loop/fs.mbt @@ -27,8 +27,12 @@ pub async fn open( mode~ : Int, context~ : String, ) -> Int { - let path = @encoding/utf8.encode(path) - perform_job_in_worker(JobForWorker::open(path, flags, mode), context~) + let path_bytes = @encoding/utf8.encode(path) + perform_job_in_worker( + JobForWorker::open(path_bytes, flags, mode), + context~, + extra=Some(path), + ) } ///| @@ -37,42 +41,67 @@ pub async fn stat( follow_symlink~ : Bool, context~ : String, ) -> @fd_util.Stat { - let path = @encoding/utf8.encode(path) + let path_bytes = @encoding/utf8.encode(path) let stat = @fd_util.Stat::new() let _ = perform_job_in_worker( - JobForWorker::stat(path, stat, follow_symlink~), + JobForWorker::stat(path_bytes, stat, follow_symlink~), context~, + extra=Some(path), ) stat } ///| pub async fn access(path : StringView, amode~ : Int, context~ : String) -> Int { - let path = @encoding/utf8.encode(path) - perform_job_in_worker(JobForWorker::access(path, amode), context~) + let path_bytes = @encoding/utf8.encode(path) + perform_job_in_worker( + JobForWorker::access(path_bytes, amode), + context~, + extra=Some(path), + ) } ///| pub async fn fsync(fd : Int, only_data~ : Bool, context~ : String) -> Unit { - perform_job_in_worker(JobForWorker::fsync(fd, only_data), context~) |> ignore + perform_job_in_worker( + JobForWorker::fsync(fd, only_data), + context~, + extra=None, + ) + |> ignore } ///| pub async fn remove(path : StringView, context~ : String) -> Unit { - let path = @encoding/utf8.encode(path) - perform_job_in_worker(JobForWorker::remove(path), context~) |> ignore + let path_bytes = @encoding/utf8.encode(path) + perform_job_in_worker( + JobForWorker::remove(path_bytes), + context~, + extra=Some(path), + ) + |> ignore } ///| pub async fn mkdir(path : StringView, mode~ : Int, context~ : String) -> Unit { - let path = @encoding/utf8.encode(path) - perform_job_in_worker(JobForWorker::mkdir(path, mode), context~) |> ignore + let path_bytes = @encoding/utf8.encode(path) + perform_job_in_worker( + JobForWorker::mkdir(path_bytes, mode), + context~, + extra=Some(path), + ) + |> ignore } ///| pub async fn rmdir(path : StringView, context~ : String) -> Unit { - let path = @encoding/utf8.encode(path) - perform_job_in_worker(JobForWorker::rmdir(path), context~) |> ignore + let path_bytes = @encoding/utf8.encode(path) + perform_job_in_worker( + JobForWorker::rmdir(path_bytes), + context~, + extra=Some(path), + ) + |> ignore } ///| @@ -81,15 +110,23 @@ extern "C" fn DirectoryEntry::null() -> DirectoryEntry = "moonbitlang_async_null ///| pub async fn readdir(dir : Directory, context~ : String) -> DirectoryEntry { let out = @ref.new(DirectoryEntry::null()) - let _ = perform_job_in_worker(JobForWorker::readdir(dir, out), context~) + let _ = perform_job_in_worker( + JobForWorker::readdir(dir, out), + context~, + extra=None, + ) out.val } ///| pub async fn realpath(path : StringView, context~ : String) -> Bytes { - let path = @encoding/utf8.encode(path) + let path_bytes = @encoding/utf8.encode(path) let out = @ref.new(@c_buffer.null) - let _ = perform_job_in_worker(JobForWorker::realpath(path, out), context~) + let _ = perform_job_in_worker( + JobForWorker::realpath(path_bytes, out), + context~, + extra=Some(path), + ) let c_path = out.val defer c_path.free() let len = c_path.strlen() diff --git a/src/internal/event_loop/network.mbt b/src/internal/event_loop/network.mbt index 6409851f..ba7b914d 100644 --- a/src/internal/event_loop/network.mbt +++ b/src/internal/event_loop/network.mbt @@ -99,7 +99,7 @@ pub async fn connect(sock : Int, addr : Bytes, context~ : String) -> Int { if err < 0 { @os_error.check_errno(context) } else if err > 0 { - raise @os_error.OSError(err, context~) + raise @os_error.OSError(err, context~, extra=None) } } else { @os_error.check_errno(context) @@ -148,12 +148,13 @@ pub async fn getaddrinfo( host : StringView, context~ : String, ) -> Result[AddrInfo, String] { - let host = @encoding/utf8.encode(host) + let host_bytes = @encoding/utf8.encode(host) let out = AddrInfoRef::new() let ret = perform_job_in_worker( - JobForWorker::getaddrinfo(host, out), + JobForWorker::getaddrinfo(host_bytes, out), allow_cancel=true, context~, + extra=Some(host), ) if ret != 0 { let c_str = gai_strerror(ret) diff --git a/src/internal/event_loop/worker_wbtest.mbt b/src/internal/event_loop/worker_wbtest.mbt index bc8055ce..89a5ac2a 100644 --- a/src/internal/event_loop/worker_wbtest.mbt +++ b/src/internal/event_loop/worker_wbtest.mbt @@ -17,7 +17,8 @@ extern "C" fn JobForWorker::sleep(time : Int) -> JobForWorker = "moonbitlang_asy ///| async fn perform_sleep_job(t : Int) -> Unit { - perform_job_in_worker(JobForWorker::sleep(t), context="") |> ignore + perform_job_in_worker(JobForWorker::sleep(t), context="", extra=None) + |> ignore } ///| diff --git a/src/os_error/error.mbt b/src/os_error/error.mbt index 9b41efe1..e1497e69 100644 --- a/src/os_error/error.mbt +++ b/src/os_error/error.mbt @@ -31,12 +31,12 @@ extern "C" fn strerror(errno : Int) -> @c_buffer.Buffer = "moonbitlang_async_err ///| pub(all) suberror OSError { - OSError(Int, context~ : String) + OSError(Int, context~ : String, extra~ : String?) } ///| pub impl Show for OSError with output(self, logger) -> Unit { - let OSError(errno, context~) = self + let OSError(errno, context~, extra~) = self let c_str = strerror(errno) let len = c_str.strlen() let data = FixedArray::make(len, (0 : Byte)) @@ -44,10 +44,13 @@ pub impl Show for OSError with output(self, logger) -> Unit { let errno_desc = @encoding/utf8.decode_lossy( data.unsafe_reinterpret_as_bytes(), ) - logger - ..write_string("OSError(") - ..write_object("\{context}: \{errno_desc}") - ..write_string(")") + logger.write_string("OSError(") + logger.write_object("\{context}: \{errno_desc}") + if extra is Some(info) { + logger.write_string(", ") + logger.write_object(info) + } + logger.write_string(")") } ///| @@ -66,6 +69,6 @@ pub fn OSError::is_EINTR(err : OSError) -> Bool { pub fn check_errno(context : String) -> Unit raise OSError { let err_code = get_errno() if err_code != 0 { - raise OSError(err_code, context~) + raise OSError(err_code, context~, extra=None) } } diff --git a/src/os_error/pkg.generated.mbti b/src/os_error/pkg.generated.mbti index 30833b9c..e0f94f27 100644 --- a/src/os_error/pkg.generated.mbti +++ b/src/os_error/pkg.generated.mbti @@ -10,7 +10,7 @@ fn is_nonblocking_io_error() -> Bool // Errors pub(all) suberror OSError { - OSError(Int, context~ : String) + OSError(Int, context~ : String, extra~ : String?) } fn OSError::is_EINTR(Self) -> Bool fn OSError::is_nonblocking_io_error(Self) -> Bool From 03e67695bb91e6bb173684bf06bf85008bbd0e8b Mon Sep 17 00:00:00 2001 From: Guest0x0 Date: Wed, 29 Oct 2025 06:04:11 +0000 Subject: [PATCH 3/4] simplify the implementation & API --- src/fs/access_test.mbt | 2 +- src/internal/event_loop/event_loop.mbt | 12 +--- src/internal/event_loop/fs.mbt | 72 +++++++---------------- src/internal/event_loop/network.mbt | 9 ++- src/internal/event_loop/worker_wbtest.mbt | 3 +- src/os_error/error.mbt | 17 +++--- src/os_error/pkg.generated.mbti | 2 +- 7 files changed, 39 insertions(+), 78 deletions(-) diff --git a/src/fs/access_test.mbt b/src/fs/access_test.mbt index a1cd12fb..f7b98f52 100644 --- a/src/fs/access_test.mbt +++ b/src/fs/access_test.mbt @@ -23,7 +23,7 @@ async test "exists" { inspect( try? ignore(@fs.open("moon.mod.json.not_exist", mode=ReadOnly)), content=( - #|Err(OSError("@fs.open(): No such file or directory", "moon.mod.json.not_exist")) + #|Err(OSError("@fs.open(): \"moon.mod.json.not_exist\": No such file or directory")) ), ) } diff --git a/src/internal/event_loop/event_loop.mbt b/src/internal/event_loop/event_loop.mbt index 642a8b2d..f14496a1 100644 --- a/src/internal/event_loop/event_loop.mbt +++ b/src/internal/event_loop/event_loop.mbt @@ -317,7 +317,6 @@ pub fn close_fd(fd : Int) -> Unit { async fn perform_job_in_worker( job : JobForWorker, context~ : String, - extra~ : StringView?, allow_cancel? : Bool = false, ) -> Int { guard curr_loop.val is Some(evloop) @@ -341,11 +340,7 @@ async fn perform_job_in_worker( @coroutine.protect_from_cancel(@coroutine.suspend) } if job.err() > 0 { - raise @os_error.OSError( - job.err(), - context~, - extra=extra.map(x => x.to_string()), - ) + raise @os_error.OSError(job.err(), context~) } else { job.ret() } @@ -385,7 +380,7 @@ pub async fn read( ret } else { let job = JobForWorker::read(fd, buf, offset, len) - perform_job_in_worker(job, context~, extra=None) + perform_job_in_worker(job, context~) } } @@ -423,7 +418,7 @@ pub async fn write( ret } else { let job = JobForWorker::write(fd, buf, offset, len) - perform_job_in_worker(job, context~, extra=None) + perform_job_in_worker(job, context~) } } @@ -441,7 +436,6 @@ pub async fn spawn( perform_job_in_worker( JobForWorker::spawn(path, args, env, stdin, stdout, stderr, cwd), context~, - extra=None, ) } diff --git a/src/internal/event_loop/fs.mbt b/src/internal/event_loop/fs.mbt index 76a33715..67679d50 100644 --- a/src/internal/event_loop/fs.mbt +++ b/src/internal/event_loop/fs.mbt @@ -28,11 +28,12 @@ pub async fn open( context~ : String, ) -> Int { let path_bytes = @encoding/utf8.encode(path) - perform_job_in_worker( - JobForWorker::open(path_bytes, flags, mode), - context~, - extra=Some(path), - ) + let job = JobForWorker::open(path_bytes, flags, mode) + perform_job_in_worker(job, context~) catch { + @os_error.OSError(errno, context~) => + raise @os_error.OSError(errno, context="\{context}: \{repr(path)}") + err => raise err + } } ///| @@ -41,67 +42,42 @@ pub async fn stat( follow_symlink~ : Bool, context~ : String, ) -> @fd_util.Stat { - let path_bytes = @encoding/utf8.encode(path) + let path = @encoding/utf8.encode(path) let stat = @fd_util.Stat::new() let _ = perform_job_in_worker( - JobForWorker::stat(path_bytes, stat, follow_symlink~), + JobForWorker::stat(path, stat, follow_symlink~), context~, - extra=Some(path), ) stat } ///| pub async fn access(path : StringView, amode~ : Int, context~ : String) -> Int { - let path_bytes = @encoding/utf8.encode(path) - perform_job_in_worker( - JobForWorker::access(path_bytes, amode), - context~, - extra=Some(path), - ) + let path = @encoding/utf8.encode(path) + perform_job_in_worker(JobForWorker::access(path, amode), context~) } ///| pub async fn fsync(fd : Int, only_data~ : Bool, context~ : String) -> Unit { - perform_job_in_worker( - JobForWorker::fsync(fd, only_data), - context~, - extra=None, - ) - |> ignore + perform_job_in_worker(JobForWorker::fsync(fd, only_data), context~) |> ignore } ///| pub async fn remove(path : StringView, context~ : String) -> Unit { - let path_bytes = @encoding/utf8.encode(path) - perform_job_in_worker( - JobForWorker::remove(path_bytes), - context~, - extra=Some(path), - ) - |> ignore + let path = @encoding/utf8.encode(path) + perform_job_in_worker(JobForWorker::remove(path), context~) |> ignore } ///| pub async fn mkdir(path : StringView, mode~ : Int, context~ : String) -> Unit { - let path_bytes = @encoding/utf8.encode(path) - perform_job_in_worker( - JobForWorker::mkdir(path_bytes, mode), - context~, - extra=Some(path), - ) - |> ignore + let path = @encoding/utf8.encode(path) + perform_job_in_worker(JobForWorker::mkdir(path, mode), context~) |> ignore } ///| pub async fn rmdir(path : StringView, context~ : String) -> Unit { - let path_bytes = @encoding/utf8.encode(path) - perform_job_in_worker( - JobForWorker::rmdir(path_bytes), - context~, - extra=Some(path), - ) - |> ignore + let path = @encoding/utf8.encode(path) + perform_job_in_worker(JobForWorker::rmdir(path), context~) |> ignore } ///| @@ -110,23 +86,15 @@ extern "C" fn DirectoryEntry::null() -> DirectoryEntry = "moonbitlang_async_null ///| pub async fn readdir(dir : Directory, context~ : String) -> DirectoryEntry { let out = @ref.new(DirectoryEntry::null()) - let _ = perform_job_in_worker( - JobForWorker::readdir(dir, out), - context~, - extra=None, - ) + let _ = perform_job_in_worker(JobForWorker::readdir(dir, out), context~) out.val } ///| pub async fn realpath(path : StringView, context~ : String) -> Bytes { - let path_bytes = @encoding/utf8.encode(path) + let path = @encoding/utf8.encode(path) let out = @ref.new(@c_buffer.null) - let _ = perform_job_in_worker( - JobForWorker::realpath(path_bytes, out), - context~, - extra=Some(path), - ) + let _ = perform_job_in_worker(JobForWorker::realpath(path, out), context~) let c_path = out.val defer c_path.free() let len = c_path.strlen() diff --git a/src/internal/event_loop/network.mbt b/src/internal/event_loop/network.mbt index ba7b914d..b5061b86 100644 --- a/src/internal/event_loop/network.mbt +++ b/src/internal/event_loop/network.mbt @@ -99,7 +99,7 @@ pub async fn connect(sock : Int, addr : Bytes, context~ : String) -> Int { if err < 0 { @os_error.check_errno(context) } else if err > 0 { - raise @os_error.OSError(err, context~, extra=None) + raise @os_error.OSError(err, context~) } } else { @os_error.check_errno(context) @@ -154,8 +154,11 @@ pub async fn getaddrinfo( JobForWorker::getaddrinfo(host_bytes, out), allow_cancel=true, context~, - extra=Some(host), - ) + ) catch { + @os_error.OSError(errno, context~) => + raise @os_error.OSError(errno, context="\{context}: \{repr(host)}") + err => raise err + } if ret != 0 { let c_str = gai_strerror(ret) let len = c_str.strlen() diff --git a/src/internal/event_loop/worker_wbtest.mbt b/src/internal/event_loop/worker_wbtest.mbt index 89a5ac2a..bc8055ce 100644 --- a/src/internal/event_loop/worker_wbtest.mbt +++ b/src/internal/event_loop/worker_wbtest.mbt @@ -17,8 +17,7 @@ extern "C" fn JobForWorker::sleep(time : Int) -> JobForWorker = "moonbitlang_asy ///| async fn perform_sleep_job(t : Int) -> Unit { - perform_job_in_worker(JobForWorker::sleep(t), context="", extra=None) - |> ignore + perform_job_in_worker(JobForWorker::sleep(t), context="") |> ignore } ///| diff --git a/src/os_error/error.mbt b/src/os_error/error.mbt index e1497e69..9b41efe1 100644 --- a/src/os_error/error.mbt +++ b/src/os_error/error.mbt @@ -31,12 +31,12 @@ extern "C" fn strerror(errno : Int) -> @c_buffer.Buffer = "moonbitlang_async_err ///| pub(all) suberror OSError { - OSError(Int, context~ : String, extra~ : String?) + OSError(Int, context~ : String) } ///| pub impl Show for OSError with output(self, logger) -> Unit { - let OSError(errno, context~, extra~) = self + let OSError(errno, context~) = self let c_str = strerror(errno) let len = c_str.strlen() let data = FixedArray::make(len, (0 : Byte)) @@ -44,13 +44,10 @@ pub impl Show for OSError with output(self, logger) -> Unit { let errno_desc = @encoding/utf8.decode_lossy( data.unsafe_reinterpret_as_bytes(), ) - logger.write_string("OSError(") - logger.write_object("\{context}: \{errno_desc}") - if extra is Some(info) { - logger.write_string(", ") - logger.write_object(info) - } - logger.write_string(")") + logger + ..write_string("OSError(") + ..write_object("\{context}: \{errno_desc}") + ..write_string(")") } ///| @@ -69,6 +66,6 @@ pub fn OSError::is_EINTR(err : OSError) -> Bool { pub fn check_errno(context : String) -> Unit raise OSError { let err_code = get_errno() if err_code != 0 { - raise OSError(err_code, context~, extra=None) + raise OSError(err_code, context~) } } diff --git a/src/os_error/pkg.generated.mbti b/src/os_error/pkg.generated.mbti index e0f94f27..30833b9c 100644 --- a/src/os_error/pkg.generated.mbti +++ b/src/os_error/pkg.generated.mbti @@ -10,7 +10,7 @@ fn is_nonblocking_io_error() -> Bool // Errors pub(all) suberror OSError { - OSError(Int, context~ : String, extra~ : String?) + OSError(Int, context~ : String) } fn OSError::is_EINTR(Self) -> Bool fn OSError::is_nonblocking_io_error(Self) -> Bool From 87989a55cac6df01ec32ae5a06651ea92d24f7a1 Mon Sep 17 00:00:00 2001 From: Guest0x0 Date: Wed, 29 Oct 2025 06:19:49 +0000 Subject: [PATCH 4/4] add extra info for more operations --- src/internal/event_loop/fs.mbt | 65 ++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/src/internal/event_loop/fs.mbt b/src/internal/event_loop/fs.mbt index 67679d50..dc3301ec 100644 --- a/src/internal/event_loop/fs.mbt +++ b/src/internal/event_loop/fs.mbt @@ -42,19 +42,27 @@ pub async fn stat( follow_symlink~ : Bool, context~ : String, ) -> @fd_util.Stat { - let path = @encoding/utf8.encode(path) + let path_bytes = @encoding/utf8.encode(path) let stat = @fd_util.Stat::new() - let _ = perform_job_in_worker( - JobForWorker::stat(path, stat, follow_symlink~), - context~, - ) + let job = JobForWorker::stat(path_bytes, stat, follow_symlink~) + try perform_job_in_worker(job, context~) catch { + @os_error.OSError(errno, context~) => + raise @os_error.OSError(errno, context="\{context}: \{repr(path)}") + err => raise err + } noraise { + _ => () + } stat } ///| pub async fn access(path : StringView, amode~ : Int, context~ : String) -> Int { - let path = @encoding/utf8.encode(path) - perform_job_in_worker(JobForWorker::access(path, amode), context~) + let path_bytes = @encoding/utf8.encode(path) + perform_job_in_worker(JobForWorker::access(path_bytes, amode), context~) catch { + @os_error.OSError(errno, context~) => + raise @os_error.OSError(errno, context="\{context}: \{repr(path)}") + err => raise err + } } ///| @@ -64,20 +72,40 @@ pub async fn fsync(fd : Int, only_data~ : Bool, context~ : String) -> Unit { ///| pub async fn remove(path : StringView, context~ : String) -> Unit { - let path = @encoding/utf8.encode(path) - perform_job_in_worker(JobForWorker::remove(path), context~) |> ignore + let path_bytes = @encoding/utf8.encode(path) + try perform_job_in_worker(JobForWorker::remove(path_bytes), context~) catch { + @os_error.OSError(errno, context~) => + raise @os_error.OSError(errno, context="\{context}: \{repr(path)}") + err => raise err + } noraise { + _ => () + } } ///| pub async fn mkdir(path : StringView, mode~ : Int, context~ : String) -> Unit { - let path = @encoding/utf8.encode(path) - perform_job_in_worker(JobForWorker::mkdir(path, mode), context~) |> ignore + let path_bytes = @encoding/utf8.encode(path) + try + perform_job_in_worker(JobForWorker::mkdir(path_bytes, mode), context~) + catch { + @os_error.OSError(errno, context~) => + raise @os_error.OSError(errno, context="\{context}: \{repr(path)}") + err => raise err + } noraise { + _ => () + } } ///| pub async fn rmdir(path : StringView, context~ : String) -> Unit { - let path = @encoding/utf8.encode(path) - perform_job_in_worker(JobForWorker::rmdir(path), context~) |> ignore + let path_bytes = @encoding/utf8.encode(path) + try perform_job_in_worker(JobForWorker::rmdir(path_bytes), context~) catch { + @os_error.OSError(errno, context~) => + raise @os_error.OSError(errno, context="\{context}: \{repr(path)}") + err => raise err + } noraise { + _ => () + } } ///| @@ -92,9 +120,16 @@ pub async fn readdir(dir : Directory, context~ : String) -> DirectoryEntry { ///| pub async fn realpath(path : StringView, context~ : String) -> Bytes { - let path = @encoding/utf8.encode(path) + let path_bytes = @encoding/utf8.encode(path) let out = @ref.new(@c_buffer.null) - let _ = perform_job_in_worker(JobForWorker::realpath(path, out), context~) + let job = JobForWorker::realpath(path_bytes, out) + try perform_job_in_worker(job, context~) catch { + @os_error.OSError(errno, context~) => + raise @os_error.OSError(errno, context="\{context}: \{repr(path)}") + err => raise err + } noraise { + _ => () + } let c_path = out.val defer c_path.free() let len = c_path.strlen()