net: retry logic on select when fail on signal (#10453)

pull/10477/head weekly.2021.24
Tomas Hellström 2021-06-16 03:07:24 +02:00 committed by GitHub
parent ffcc6cf6d2
commit 2f9e03b360
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 24 additions and 3 deletions

View File

@ -65,6 +65,28 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
return C.FD_ISSET(handle, &set) return C.FD_ISSET(handle, &set)
} }
// select_with_retry will retry the select if select is failing
// due to interrupted system call. This can happen on signals
// for example the GC Boehm uses signals internally on garbage
// collection
[inline]
fn select_with_retry(handle int, test Select, timeout time.Duration) ?bool {
mut retries := 3
for retries > 0 {
ready := @select(handle, test, timeout) or {
if err.code == 4 {
// signal! lets retry max 3 times
retries -= 1
continue
}
// we got other error
return err
}
return ready
}
return error('failed to @select more that three times due to interrupted system call')
}
// wait_for_common wraps the common wait code // wait_for_common wraps the common wait code
fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ? { fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ? {
if deadline.unix == 0 { if deadline.unix == 0 {
@ -73,7 +95,7 @@ fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test S
if timeout < 0 && timeout != net.infinite_timeout { if timeout < 0 && timeout != net.infinite_timeout {
return err_timed_out return err_timed_out
} }
ready := @select(handle, test, timeout) ? ready := select_with_retry(handle, test, timeout) ?
if ready { if ready {
return return
} }
@ -87,8 +109,7 @@ fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test S
// timed out // timed out
return err_timed_out return err_timed_out
} }
ready := select_with_retry(handle, test, timeout) ?
ready := @select(handle, test, d_timeout) ?
if ready { if ready {
return return
} }