1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

net: select with deadlines (#14369)

This commit is contained in:
Emily Hudson 2022-05-11 16:03:48 -05:00 committed by GitHub
parent cd4fa041ff
commit c19b037880
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -65,56 +65,51 @@ 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] [inline]
fn select_with_retry(handle int, test Select, timeout time.Duration) ?bool { fn select_deadline(handle int, test Select, deadline time.Time) ?bool {
mut retries := 10 // if we have a 0 deadline here then the timeout that was passed was infinite...
for retries > 0 { infinite := deadline.unix_time() == 0
for infinite || time.now() <= deadline {
timeout := if infinite { net.infinite_timeout } else { deadline - time.now() }
ready := @select(handle, test, timeout) or { ready := @select(handle, test, timeout) or {
if err.code() == 4 { if err.code() == 4 {
// signal! lets retry max 10 times // Spurious wakeup from signal, keep waiting
// suspend thread with sleep to let the gc get
// cycles in the case the Bohem gc is interupting
time.sleep(1 * time.millisecond)
retries -= 1
continue continue
} }
// we got other error
// NOT a spurious wakeup
return err return err
} }
return ready return ready
} }
return error('failed to @select more that three times due to interrupted system call')
// Deadline elapsed
return false
} }
// 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 { // Convert timeouts to deadlines
// do not accept negative timeout real_deadline := if timeout == net.infinite_timeout {
if timeout < 0 { time.unix(0)
return err_timed_out } else if timeout == 0 {
} // No timeout set, so assume deadline
ready := select_with_retry(handle, test, timeout) ? deadline
if ready { } else if timeout < 0 {
return // TODO(emily): Do something nicer here :)
} panic('invalid negative timeout')
return err_timed_out } else {
// timeout
time.now().add(timeout)
} }
// Convert the deadline into a timeout
// and use that ready := select_deadline(handle, test, real_deadline) ?
d_timeout := deadline.unix - time.now().unix
if d_timeout < 0 {
// deadline is in the past so this has already
// timed out
return err_timed_out
}
ready := select_with_retry(handle, test, timeout) ?
if ready { if ready {
return return
} }
return err_timed_out return err_timed_out
} }