(
&self,
address: PyObjectRef,
caller: &str,
vm: &VirtualMachine,
)
| 1337 | } |
| 1338 | |
| 1339 | fn connect_inner( |
| 1340 | &self, |
| 1341 | address: PyObjectRef, |
| 1342 | caller: &str, |
| 1343 | vm: &VirtualMachine, |
| 1344 | ) -> Result<(), IoOrPyException> { |
| 1345 | let sock_addr = self.extract_address(address, caller, vm)?; |
| 1346 | |
| 1347 | let sock = self.sock()?; |
| 1348 | let err = match vm.allow_threads(|| sock.connect(&sock_addr)) { |
| 1349 | Ok(()) => return Ok(()), |
| 1350 | Err(e) => e, |
| 1351 | }; |
| 1352 | |
| 1353 | let wait_connect = if err.kind() == io::ErrorKind::Interrupted { |
| 1354 | vm.check_signals()?; |
| 1355 | self.timeout.load() != 0.0 |
| 1356 | } else { |
| 1357 | #[cfg(unix)] |
| 1358 | use c::EINPROGRESS; |
| 1359 | #[cfg(windows)] |
| 1360 | use c::WSAEWOULDBLOCK as EINPROGRESS; |
| 1361 | |
| 1362 | self.timeout.load() > 0.0 && err.raw_os_error() == Some(EINPROGRESS) |
| 1363 | }; |
| 1364 | |
| 1365 | if wait_connect { |
| 1366 | // basically, connect() is async, and it registers an "error" on the socket when it's |
| 1367 | // done connecting. SelectKind::Connect fills the errorfds fd_set, so if we wake up |
| 1368 | // from poll and the error is EISCONN then we know that the connect is done |
| 1369 | self.sock_op(vm, SelectKind::Connect, || { |
| 1370 | let sock = self.sock()?; |
| 1371 | let err = sock.take_error()?; |
| 1372 | match err { |
| 1373 | Some(e) if e.posix_errno() == libc::EISCONN => Ok(()), |
| 1374 | Some(e) => Err(e), |
| 1375 | // TODO: is this accurate? |
| 1376 | None => Ok(()), |
| 1377 | } |
| 1378 | }) |
| 1379 | } else { |
| 1380 | Err(err.into()) |
| 1381 | } |
| 1382 | } |
| 1383 | } |
| 1384 | |
| 1385 | impl DefaultConstructor for PySocket {} |
no test coverage detected