mirror of
https://github.com/vlang/v.git
synced 2025-09-13 01:16:02 -04:00
net: fix handling of spurious wake-up signals, lost when calling select() in mbedtls and openssl (continue on C.EINTR) (#19600)
This commit is contained in:
parent
29511bcc49
commit
772eb1ed12
@ -545,40 +545,54 @@ fn @select(handle int, test Select, timeout time.Duration) !bool {
|
|||||||
eprintln('${@METHOD} handle: ${handle}, timeout: ${timeout}')
|
eprintln('${@METHOD} handle: ${handle}, timeout: ${timeout}')
|
||||||
}
|
}
|
||||||
set := C.fd_set{}
|
set := C.fd_set{}
|
||||||
|
|
||||||
C.FD_ZERO(&set)
|
C.FD_ZERO(&set)
|
||||||
C.FD_SET(handle, &set)
|
C.FD_SET(handle, &set)
|
||||||
|
|
||||||
seconds := timeout.milliseconds() / 1000
|
deadline := time.now().add(timeout)
|
||||||
microseconds := timeout - (seconds * time.second)
|
mut remaining_time := timeout.milliseconds()
|
||||||
mut tt := C.timeval{
|
for remaining_time > 0 {
|
||||||
tv_sec: u64(seconds)
|
seconds := remaining_time / 1000
|
||||||
tv_usec: u64(microseconds)
|
microseconds := (remaining_time % 1000) * 1000
|
||||||
}
|
|
||||||
|
|
||||||
mut timeval_timeout := &tt
|
tt := C.timeval{
|
||||||
|
tv_sec: u64(seconds)
|
||||||
// infinite timeout is signaled by passing null as the timeout to
|
tv_usec: u64(microseconds)
|
||||||
// select
|
|
||||||
if timeout == net.infinite_timeout {
|
|
||||||
timeval_timeout = &C.timeval(unsafe { nil })
|
|
||||||
}
|
|
||||||
|
|
||||||
match test {
|
|
||||||
.read {
|
|
||||||
net.socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))!
|
|
||||||
}
|
}
|
||||||
.write {
|
timeval_timeout := if timeout < 0 {
|
||||||
net.socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))!
|
&C.timeval(unsafe { nil })
|
||||||
|
} else {
|
||||||
|
&tt
|
||||||
}
|
}
|
||||||
.except {
|
|
||||||
net.socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))!
|
mut res := -1
|
||||||
|
match test {
|
||||||
|
.read {
|
||||||
|
res = net.socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))!
|
||||||
|
}
|
||||||
|
.write {
|
||||||
|
res = net.socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))!
|
||||||
|
}
|
||||||
|
.except {
|
||||||
|
res = net.socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if res < 0 {
|
||||||
|
if C.errno == C.EINTR {
|
||||||
|
// errno is 4, Spurious wakeup from signal, keep waiting
|
||||||
|
remaining_time = (deadline - time.now()).milliseconds()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return error_with_code('Select failed: ${res}', C.errno)
|
||||||
|
} else if res == 0 {
|
||||||
|
return net.err_timed_out
|
||||||
|
}
|
||||||
|
|
||||||
|
res = C.FD_ISSET(handle, &set)
|
||||||
|
$if trace_ssl ? {
|
||||||
|
eprintln('${@METHOD} ---> res: ${res}')
|
||||||
|
}
|
||||||
|
return res != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
res := C.FD_ISSET(handle, &set)
|
return net.err_timed_out
|
||||||
$if trace_ssl ? {
|
|
||||||
eprintln('${@METHOD} ---> res: ${res}')
|
|
||||||
}
|
|
||||||
return res != 0
|
|
||||||
}
|
}
|
||||||
|
@ -410,55 +410,60 @@ pub fn (mut s SSLConn) write_string(str string) !int {
|
|||||||
return s.write_ptr(str.str, str.len)
|
return s.write_ptr(str.str, str.len)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
This is basically a copy of Emily socket implementation of select.
|
|
||||||
This have to be consolidated into common net lib features
|
|
||||||
when merging this to V
|
|
||||||
*/
|
|
||||||
// [typedef]
|
|
||||||
// pub struct C.fd_set {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Select waits for an io operation (specified by parameter `test`) to be available
|
// Select waits for an io operation (specified by parameter `test`) to be available
|
||||||
fn @select(handle int, test Select, timeout time.Duration) !bool {
|
fn @select(handle int, test Select, timeout time.Duration) !bool {
|
||||||
$if trace_ssl ? {
|
$if trace_ssl ? {
|
||||||
eprintln('${@METHOD} handle: ${handle}, timeout: ${timeout}')
|
eprintln('${@METHOD} handle: ${handle}, timeout: ${timeout}')
|
||||||
}
|
}
|
||||||
set := C.fd_set{}
|
set := C.fd_set{}
|
||||||
|
|
||||||
C.FD_ZERO(&set)
|
C.FD_ZERO(&set)
|
||||||
C.FD_SET(handle, &set)
|
C.FD_SET(handle, &set)
|
||||||
|
|
||||||
seconds := timeout.milliseconds() / 1000
|
deadline := time.now().add(timeout)
|
||||||
microseconds := timeout - (seconds * time.second)
|
mut remaining_time := timeout.milliseconds()
|
||||||
mut tt := C.timeval{
|
for remaining_time > 0 {
|
||||||
tv_sec: u64(seconds)
|
seconds := remaining_time / 1000
|
||||||
tv_usec: u64(microseconds)
|
microseconds := (remaining_time % 1000) * 1000
|
||||||
}
|
|
||||||
|
|
||||||
mut timeval_timeout := &tt
|
tt := C.timeval{
|
||||||
|
tv_sec: u64(seconds)
|
||||||
// infinite timeout is signaled by passing null as the timeout to
|
tv_usec: u64(microseconds)
|
||||||
// select
|
|
||||||
if timeout == net.infinite_timeout {
|
|
||||||
timeval_timeout = &C.timeval(unsafe { nil })
|
|
||||||
}
|
|
||||||
|
|
||||||
match test {
|
|
||||||
.read {
|
|
||||||
net.socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))!
|
|
||||||
}
|
}
|
||||||
.write {
|
timeval_timeout := if timeout < 0 {
|
||||||
net.socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))!
|
&C.timeval(unsafe { nil })
|
||||||
|
} else {
|
||||||
|
&tt
|
||||||
}
|
}
|
||||||
.except {
|
|
||||||
net.socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))!
|
mut res := -1
|
||||||
|
match test {
|
||||||
|
.read {
|
||||||
|
res = net.socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))!
|
||||||
|
}
|
||||||
|
.write {
|
||||||
|
res = net.socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))!
|
||||||
|
}
|
||||||
|
.except {
|
||||||
|
res = net.socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if res < 0 {
|
||||||
|
if C.errno == C.EINTR {
|
||||||
|
// errno is 4, Spurious wakeup from signal, keep waiting
|
||||||
|
remaining_time = (deadline - time.now()).milliseconds()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return error_with_code('Select failed: ${res}', C.errno)
|
||||||
|
} else if res == 0 {
|
||||||
|
return net.err_timed_out
|
||||||
|
}
|
||||||
|
|
||||||
|
res = C.FD_ISSET(handle, &set)
|
||||||
|
$if trace_ssl ? {
|
||||||
|
eprintln('${@METHOD} ---> res: ${res}')
|
||||||
|
}
|
||||||
|
return res != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
res := C.FD_ISSET(handle, &set)
|
return net.err_timed_out
|
||||||
$if trace_ssl ? {
|
|
||||||
eprintln('${@METHOD} ---> res: ${res}')
|
|
||||||
}
|
|
||||||
return res != 0
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user