Skip to content

Commit 7da79fd

Browse files
authored
os: improve robustness of create_folder_when_it_does_not_exist/1 (fix CI false positives for vab-compiles-v-examples) (#22548)
1 parent 8556353 commit 7da79fd

File tree

3 files changed

+53
-7
lines changed

3 files changed

+53
-7
lines changed

vlib/os/os.v

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -800,15 +800,27 @@ fn create_folder_when_it_does_not_exist(path string) {
800800
if is_dir(path) || is_link(path) {
801801
return
802802
}
803-
mkdir_all(path, mode: 0o700) or {
804-
if is_dir(path) || is_link(path) {
805-
// A race had been won, and the `path` folder had been created,
806-
// by another concurrent V executable, since the folder now exists,
807-
// but it did not right before ... we will just use it too.
808-
return
803+
mut error_msg := ''
804+
for _ in 0 .. 10 {
805+
mkdir_all(path, mode: 0o700) or {
806+
if is_dir(path) || is_link(path) {
807+
// A race had been won, and the `path` folder had been created, by another concurrent V program.
808+
// We are fine with that, since the folder now exists, even though this process did not create it.
809+
// We can just use it too ¯\_(ツ)_/¯ .
810+
return
811+
}
812+
error_msg = err.msg()
813+
sleep_ms(1) // wait a bit, before a retry, to let the other process finish its folder creation
814+
continue
809815
}
810-
panic(err)
816+
break
817+
}
818+
if is_dir(path) || is_link(path) {
819+
return
811820
}
821+
// There was something wrong, that could not be solved, by just retrying
822+
// There is no choice, but to report it back :-\
823+
panic(error_msg)
812824
}
813825

814826
fn xdg_home_folder(ename string, lpath string) string {

vlib/os/sleeping.c.v

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module os
2+
3+
pub struct C.timespec {
4+
pub mut:
5+
tv_sec i64
6+
tv_nsec i64
7+
}
8+
9+
fn C.nanosleep(req &C.timespec, rem &C.timespec) int
10+
11+
// sleep_ms provides a cross platform way to sleep, without having to `import time` for a time.sleep/1 call.
12+
fn sleep_ms(ms i64) {
13+
$if windows {
14+
C.Sleep(u32(ms))
15+
} $else {
16+
mut req := C.timespec{ms / 1000, 1_000_000 * (ms % 1000)}
17+
rem := C.timespec{}
18+
for C.nanosleep(&req, &rem) < 0 {
19+
if C.errno == C.EINTR {
20+
req = rem
21+
} else {
22+
break
23+
}
24+
}
25+
}
26+
}

vlib/os/sleeping.js.v

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module os
2+
3+
// sleep_ms suspends the execution for a given duration (in milliseconds), without having to `import time` for a single time.sleep/1 call.
4+
fn sleep_ms(dur i64) {
5+
#let now = new Date().getTime()
6+
#let toWait = BigInt(dur)
7+
#while (new Date().getTime() < now + Number(toWait)) {}
8+
}

0 commit comments

Comments
 (0)