Skip to content

mkdir: do not ignore EEXIST on non-recursive creation - #13986

Open
l46983284-cpu wants to merge 1 commit into
uutils:mainfrom
l46983284-cpu:fix-13970-mkdir-concurrent-eexist
Open

mkdir: do not ignore EEXIST on non-recursive creation#13986
l46983284-cpu wants to merge 1 commit into
uutils:mainfrom
l46983284-cpu:fix-13970-mkdir-concurrent-eexist

Conversation

@l46983284-cpu

Copy link
Copy Markdown
Contributor

Fixes #13970.

mkdir without -p incorrectly swallows EEXIST when the target path already exists as a directory. In create_single_dir, the error branch Err(_) if path.is_dir() returns Ok(()) unconditionally, without checking whether recursive (-p) mode was requested.

This is a logic bug: a non-recursive mkdir on an existing directory must fail per POSIX, but currently exits 0. Under concurrent invocation, this also allows multiple racing processes to all "succeed" in creating the same directory.

Fix: require config.recursive || is_parent before allowing the EEXISTOk(()) fallback. This matches GNU mkdir behavior and the existing test expectations.

Regression tests:

  • test_mkdir_concurrent_creation: concurrent mkdir -p on the same path — all processes must succeed (valid for -p).
  • test_mkdir_concurrent_non_recursive: concurrent mkdir without -p on the same path — exactly one process must win per round.

Verified on bare-metal Linux and in a sandboxed environment: 500 concurrent rounds on main showed double-wins (both processes exiting 0), while this branch showed 0 double-wins. All existing tests pass.

Fixes uutils#13970

Signed-off-by: Alex Chen <l46983284@gmail.com>
@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/misc/empty-backup-suffix. tests/misc/empty-backup-suffix is passing on 'main'. Maybe you have to rebase?
GNU test failed: tests/misc/uname-labeled. tests/misc/uname-labeled is passing on 'main'. Maybe you have to rebase?
Skip an intermittent issue tests/date/date-locale-hour (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tail/tail-n0f (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/cut/bounded-memory (passes in this run but fails in the 'main' branch)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mkdir: exits 0 despite EEXIST from the kernel under concurrent invocation (breaks mkdir-as-mutex)

1 participant