- if SocketDescriptor::new(us.clone()).send_data(&initial_send, true) != initial_send.len() {
- // We should essentially always have enough room in a TCP socket buffer to send the
- // initial 10s of bytes, if not, just give up as hopeless.
- eprintln!("Failed to write first full message to socket!");
- peer_manager.socket_disconnected(&SocketDescriptor::new(Arc::clone(&us)));
- } else {
+ // We should essentially always have enough room in a TCP socket buffer to send the
+ // initial 10s of bytes. However, tokio running in single-threaded mode will always
+ // fail writes and wake us back up later to write. Thus, we handle a single
+ // std::task::Poll::Pending but still expect to write the full set of bytes at once
+ // and use a relatively tight timeout.
+ if let Ok(Ok(())) = tokio::time::timeout(Duration::from_millis(100), async {
+ loop {
+ match SocketDescriptor::new(us.clone()).send_data(&initial_send, true) {
+ v if v == initial_send.len() => break Ok(()),
+ 0 => {
+ write_receiver.recv().await;
+ // In theory we could check for if we've been instructed to disconnect
+ // the peer here, but its OK to just skip it - we'll check for it in
+ // schedule_read prior to any relevant calls into RL.
+ },
+ _ => {
+ eprintln!("Failed to write first full message to socket!");
+ peer_manager.socket_disconnected(&SocketDescriptor::new(Arc::clone(&us)));
+ break Err(());
+ }
+ }
+ }
+ }).await {