Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-12569] createDirectory(at: ..., withIntermediateDirectories:true) fails spuriously with EEXIST if it races #3259

Closed
benlangmuir opened this issue Apr 10, 2020 · 3 comments

Comments

@benlangmuir
Copy link
Member

Previous ID SR-12569
Radar rdar://problem/62201758
Original Reporter @benlangmuir
Type Bug
Status Closed
Resolution Done
Environment

swift-DEVELOPMENT-SNAPSHOT-2020-04-06-a

Additional Detail from JIRA
Votes 0
Component/s Foundation
Labels Bug
Assignee None
Priority Medium

md5: de0166218244431d1d35fb688f5d0f19

relates to:

  • SR-12272 FileManager temporary directory creation not thread-safe on Linux

Issue Description:

If you concurrently call

createDirectory(at: ..., withIntermediateDirectories: true)

for two directories that share a common parent (e.g. /a/b/ and /a/c) and the parent does not exist, it can fail spuriously with EEXIST using corelibs-foundation. On macOS Foundation it does not fail this way. This caused a test failure in sourcekit-lsp when running tests in parallel that we had to workaround[0].

Reproducer (you may need to run it a few times):

import Foundation

let base = URL(fileURLWithPath: "/tmp/createDirectoryTest", isDirectory: true)
let fm = FileManager.default

_ = try? fm.removeItem(at: base)

print("serial")
for i in 0..<2 {
  try! fm.createDirectory(at: base.appendingPathComponent("\(i)"), withIntermediateDirectories: true)
}
try! fm.removeItem(at: base)
print("-> OK")

print("parallel")
for _ in 0..<10 {
  DispatchQueue.concurrentPerform(iterations: 2) { i in
    try! fm.createDirectory(at: base.appendingPathComponent("\(i)"), withIntermediateDirectories: true)
  }
  try! fm.removeItem(at: base)
}
print("-> OK")
$ swiftc createDirectoryTest.swift && ./createDirectoryTest
serial
-> OK
parallel
Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=NSCocoaErrorDomain Code=516 "A file with the same name already exists.": file createDirectoryTest.swift, line 18

[0] https://ci.swift.org/job/swift-PR-Linux-smoke-test/21501/ rdar://61545973

 <EXPR>:0: error: CodeActionTests.testSemanticRefactorLocalRenameResult : threw error "Error Domain=NSCocoaErrorDomain Code=516 "A file with the same name already exists.""
@beccadax
Copy link
Contributor

@swift-ci create

@spevans
Copy link
Collaborator

spevans commented Jun 23, 2020

This should be fixed by #2700
and seems to work ok with swift-DEVELOPMENT-SNAPSHOT-2020-06-22-a

$ ~/swift-DEVELOPMENT-SNAPSHOT-2020-06-22-a-ubuntu18.04/usr/bin/swift jiras/sr-12569.swift 
serial
-> OK
parallel
-> OK
$ ~/swift-DEVELOPMENT-SNAPSHOT-2020-06-22-a-ubuntu18.04/usr/bin/swift jiras/sr-12569.swift 
serial
-> OK
parallel
-> OK
$ ~/swift-DEVELOPMENT-SNAPSHOT-2020-06-22-a-ubuntu18.04/usr/bin/swift jiras/sr-12569.swift 
serial
-> OK
parallel
-> OK

@benlangmuir
Copy link
Member Author

Reverting workarounds to test:

apple/indexstore-db#105

apple/sourcekit-lsp#291

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants