Skip to content

Commit 566bff2

Browse files
committed
fix(runPipelineNode): unmounting overlapping paths
If multiple paths are mounted such that one is a parent of the other, then you may encounter the following exceptions: ``` Rejected promise returned by test. Reason: ErrnoError { code: 'EINVAL', errno: 28, message: 'Invalid argument', } Rejected promise returned by test. Reason: ErrnoError { code: 'ENOENT', errno: 44, message: 'No such file or directory', } ``` This fix will determine paths that are safely unmountable, and only unmount each path once.
1 parent 6e335dc commit 566bff2

File tree

13 files changed

+93
-6
lines changed

13 files changed

+93
-6
lines changed

packages/compress-stringify/python/itkwasm-compress-stringify-emscripten/itkwasm_compress_stringify_emscripten/js_package.py

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

packages/core/typescript/itk-wasm/src/pipeline/run-pipeline-node.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,26 @@ async function runPipelineNode (
5050
pipelinePath
5151
)) as PipelineEmscriptenModule
5252
const mountedDirs: Set<string> = new Set()
53+
const unmountable: Set<string> = new Set()
5354
if (typeof mountDirs !== 'undefined') {
5455
mountDirs.forEach((dir) => {
5556
mountedDirs.add(Module.mountDir(dir))
5657
})
58+
/**
59+
* Identify mountable dirs. Some paths may be parent to others.
60+
* Only keep the parent paths, to avoid error when unmounting.
61+
*/
62+
Array.from(mountedDirs)
63+
.filter((x, _, a) => a.every((y) => x === y || !x.includes(y)))
64+
.forEach((dir) => unmountable.add(dir)
65+
)
5766
}
5867
if (typeof mountDirs !== 'undefined') {
5968
args = replaceArgumentsWithEmscriptenPaths(args, mountDirs)
6069
}
6170
const result = runPipelineEmscripten(Module, args, outputs, inputs)
6271
if (typeof mountDirs !== 'undefined') {
63-
mountedDirs.forEach((dir) => {
72+
unmountable.forEach((dir) => {
6473
Module.unmountDir(dir)
6574
})
6675
}

packages/core/typescript/itk-wasm/test/node/pipeline/run-pipeline-node-test.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,84 @@ test('runPipelineNode uses input and output text and binary data via memory io',
170170
)
171171
})
172172

173+
test('runPipelineNode uses input and output text and binary files', (t) => {
174+
const pipelinePath = path.resolve(
175+
'test',
176+
'pipelines',
177+
'emscripten-build',
178+
'input-output-files-pipeline',
179+
'input-output-files-test'
180+
)
181+
const testInputTextFile = path.resolve(
182+
'test',
183+
'data',
184+
'cow.iwm',
185+
'index.json'
186+
)
187+
const testInputBinFile = path.resolve(
188+
'test',
189+
'data',
190+
'cow.iwm',
191+
'data',
192+
'cells.raw'
193+
)
194+
const testOutputTextFile = path.resolve(
195+
'test',
196+
'data',
197+
'cow.iwm',
198+
'data',
199+
'output.txt'
200+
)
201+
const testOutputBinFile = path.resolve(
202+
'test',
203+
'data',
204+
'cow.iwm',
205+
'data',
206+
'output.bin'
207+
)
208+
209+
const args = [
210+
'--memory-io',
211+
'--input-text-stream',
212+
'0',
213+
'--input-binary-stream',
214+
'1',
215+
'0',
216+
'1',
217+
testOutputTextFile,
218+
testOutputBinFile,
219+
'-f',
220+
'--input-text-file',
221+
testInputTextFile,
222+
'--input-binary-file',
223+
testInputBinFile,
224+
]
225+
const desiredOutputs = [
226+
{ type: InterfaceTypes.TextStream },
227+
{ type: InterfaceTypes.BinaryStream }
228+
]
229+
const inputs = [
230+
{ type: InterfaceTypes.TextStream, data: { data: 'The answer is 42.' } },
231+
{
232+
type: InterfaceTypes.BinaryStream,
233+
data: { data: new Uint8Array([222, 173, 190, 239]) }
234+
}
235+
]
236+
237+
const mountDirs = new Set()
238+
mountDirs.add(path.dirname(testInputTextFile))
239+
mountDirs.add(path.dirname(testInputBinFile))
240+
mountDirs.add(path.dirname(testOutputTextFile))
241+
mountDirs.add(path.dirname(testOutputBinFile))
242+
243+
return runPipelineNode(pipelinePath, args, desiredOutputs, inputs, mountDirs).then(
244+
function ({ stdout, stderr, outputs }) {
245+
t.is(outputs[0].type, InterfaceTypes.TextStream)
246+
t.is(outputs[1].type, InterfaceTypes.BinaryStream)
247+
}
248+
)
249+
})
250+
173251
test('runPipelineNode uses input and output json data via memory io', (t) => {
174252
const pipelinePath = path.resolve(
175253
'test',

packages/dicom/python/itkwasm-dicom-emscripten/itkwasm_dicom_emscripten/js_package.py

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)