Skip to content

Commit c19b037

Browse files
authored
net: select with deadlines (#14369)
1 parent cd4fa04 commit c19b037

File tree

1 file changed

+28
-33
lines changed

1 file changed

+28
-33
lines changed

vlib/net/common.v

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -65,56 +65,51 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
6565
return C.FD_ISSET(handle, &set)
6666
}
6767

68-
// select_with_retry will retry the select if select is failing
69-
// due to interrupted system call. This can happen on signals
70-
// for example the GC Boehm uses signals internally on garbage
71-
// collection
7268
[inline]
73-
fn select_with_retry(handle int, test Select, timeout time.Duration) ?bool {
74-
mut retries := 10
75-
for retries > 0 {
69+
fn select_deadline(handle int, test Select, deadline time.Time) ?bool {
70+
// if we have a 0 deadline here then the timeout that was passed was infinite...
71+
infinite := deadline.unix_time() == 0
72+
for infinite || time.now() <= deadline {
73+
timeout := if infinite { net.infinite_timeout } else { deadline - time.now() }
7674
ready := @select(handle, test, timeout) or {
7775
if err.code() == 4 {
78-
// signal! lets retry max 10 times
79-
// suspend thread with sleep to let the gc get
80-
// cycles in the case the Bohem gc is interupting
81-
time.sleep(1 * time.millisecond)
82-
retries -= 1
76+
// Spurious wakeup from signal, keep waiting
8377
continue
8478
}
85-
// we got other error
79+
80+
// NOT a spurious wakeup
8681
return err
8782
}
83+
8884
return ready
8985
}
90-
return error('failed to @select more that three times due to interrupted system call')
86+
87+
// Deadline elapsed
88+
return false
9189
}
9290

9391
// wait_for_common wraps the common wait code
9492
fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ? {
95-
if deadline.unix == 0 {
96-
// do not accept negative timeout
97-
if timeout < 0 {
98-
return err_timed_out
99-
}
100-
ready := select_with_retry(handle, test, timeout) ?
101-
if ready {
102-
return
103-
}
104-
return err_timed_out
93+
// Convert timeouts to deadlines
94+
real_deadline := if timeout == net.infinite_timeout {
95+
time.unix(0)
96+
} else if timeout == 0 {
97+
// No timeout set, so assume deadline
98+
deadline
99+
} else if timeout < 0 {
100+
// TODO(emily): Do something nicer here :)
101+
panic('invalid negative timeout')
102+
} else {
103+
// timeout
104+
time.now().add(timeout)
105105
}
106-
// Convert the deadline into a timeout
107-
// and use that
108-
d_timeout := deadline.unix - time.now().unix
109-
if d_timeout < 0 {
110-
// deadline is in the past so this has already
111-
// timed out
112-
return err_timed_out
113-
}
114-
ready := select_with_retry(handle, test, timeout) ?
106+
107+
ready := select_deadline(handle, test, real_deadline) ?
108+
115109
if ready {
116110
return
117111
}
112+
118113
return err_timed_out
119114
}
120115

0 commit comments

Comments
 (0)