diff --git a/changelog.md b/changelog.md index b217aea..c03ca90 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # Changelog +## 2026-03-05 - 1.3.2 - fix(provider(node)) +use synchronous readdir to avoid partial results on some filesystems (e.g., XFS) when the process receives signals + +- Replaced async fs.readdir with fsSync.readdirSync in ts/providers/smartfs.provider.node.ts +- Added comments explaining that async readdir can return partial results on XFS/mounted filesystems when the process receives signals; synchronous readdirSync completes the getdents64 syscall without event-loop interruption + ## 2025-12-16 - 1.3.1 - fix(docs) docs(readme): add "Directory Copy & Move" section with examples and options diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 31b1435..9ef43fb 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@push.rocks/smartfs', - version: '1.3.1', + version: '1.3.2', description: 'a cross platform extendable fs module' } diff --git a/ts/providers/smartfs.provider.node.ts b/ts/providers/smartfs.provider.node.ts index b5d5efa..580f74b 100644 --- a/ts/providers/smartfs.provider.node.ts +++ b/ts/providers/smartfs.provider.node.ts @@ -158,7 +158,11 @@ export class SmartFsProviderNode implements ISmartFsProvider { if (options?.recursive) { await this.listDirectoryRecursive(path, entries, options); } else { - const dirents = await fs.readdir(path, { withFileTypes: true }); + // Use readdirSync for reliability — async readdir can return partial results + // on XFS/mounted filesystems when the process receives signals (e.g., from + // SmartExit/smartshell process group management). The synchronous version + // completes the entire getdents64 syscall without event loop interruption. + const dirents = fsSync.readdirSync(path, { withFileTypes: true }); for (const dirent of dirents) { const entryPath = pathModule.join(path, dirent.name); @@ -196,7 +200,8 @@ export class SmartFsProviderNode implements ISmartFsProvider { entries: IDirectoryEntry[], options?: IListOptions, ): Promise { - const dirents = await fs.readdir(path, { withFileTypes: true }); + // Use readdirSync for reliability — see listDirectory comment + const dirents = fsSync.readdirSync(path, { withFileTypes: true }); for (const dirent of dirents) { const entryPath = pathModule.join(path, dirent.name);