aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/src/dets.erl
diff options
context:
space:
mode:
authorHans Bolinder <[email protected]>2014-04-10 15:23:44 +0200
committerHans Bolinder <[email protected]>2014-10-23 08:59:29 +0200
commit89c5bc9a243d7f0ba8e43b52b9addadccdb7d1ca (patch)
tree3faeb5fb24999a54b190bac9b844a89e93d9ac54 /lib/stdlib/src/dets.erl
parentcd5628a99bff391377042f93e8d85da818235217 (diff)
downloadotp-89c5bc9a243d7f0ba8e43b52b9addadccdb7d1ca.tar.gz
otp-89c5bc9a243d7f0ba8e43b52b9addadccdb7d1ca.tar.bz2
otp-89c5bc9a243d7f0ba8e43b52b9addadccdb7d1ca.zip
Fix rare race condition in Dets
The correction is due to the the evil testcase dets_SUITE:simultaneous_open(). If the process repairing a Dets file is killed (should normally never happen), and another process tries to repair the file, a temporary file from the first process could live on for a while, even after a successful call to file:delete(). This has only been seen on W-nd-ows, where it is a known problem. There are other ways to deal with the problem (rename the file; use some other filename), but we continue using one certain filename in order to be as backwards compatible as possible.
Diffstat (limited to 'lib/stdlib/src/dets.erl')
-rw-r--r--lib/stdlib/src/dets.erl25
1 files changed, 15 insertions, 10 deletions
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl
index 76e03bbfaa..a4bd45ea19 100644
--- a/lib/stdlib/src/dets.erl
+++ b/lib/stdlib/src/dets.erl
@@ -2839,17 +2839,22 @@ fsck_try(Fd, Tab, FH, Fname, SlotNumbers, Version) ->
tempfile(Fname) ->
Tmp = lists:concat([Fname, ".TMP"]),
- tempfile(Tmp, 10).
-
-tempfile(Tmp, 0) ->
- Tmp;
-tempfile(Tmp, N) ->
case file:delete(Tmp) of
- {error, eacces} -> % 'dets_process_died' happened anyway... (W-nd-ws)
- timer:sleep(1000),
- tempfile(Tmp, N-1);
- _ ->
- Tmp
+ {error, _Reason} -> % typically enoent
+ ok;
+ ok ->
+ assure_no_file(Tmp)
+ end,
+ Tmp.
+
+assure_no_file(File) ->
+ case file:read_file_info(File) of
+ {ok, _FileInfo} ->
+ %% Wait for some other process to close the file:
+ timer:sleep(100),
+ assure_no_file(File);
+ {error, _} ->
+ ok
end.
%% -> {ok, NewHead} | {try_again, integer()} | Error