Skip to content

Check if connection is still active after send attempt#8

Open
polachok wants to merge 1 commit intoparitytech:masterfrom
polachok:connection-is-stuck
Open

Check if connection is still active after send attempt#8
polachok wants to merge 1 commit intoparitytech:masterfrom
polachok:connection-is-stuck

Conversation

@polachok
Copy link

@polachok polachok commented Jul 20, 2021

I'm seeing a problem with connection getting stuck after its buffer overflows.

It's easily reproduced using the following code for server and any websocket client (I used python):

extern crate env_logger;
extern crate parity_ws as ws;

use std::time::Duration;

use ws::listen;

struct Connection(ws::Sender);

impl ws::Handler for Connection {
    fn on_message(&mut self, msg: ws::Message) -> Result<(), ws::Error> {
        let out = self.0.clone();
        println!("Server got message '{}'. ", msg);

        std::thread::spawn(move || {
            println!("new connection #{}", out.connection_id());
            loop {
                let fill: String = (0..1024 * 1024).map(|_| 'a').collect();
                let msg = format!("{{\"kek\": \"{}\"}}", fill);
                let len = msg.len();
                match out.send(msg) {
                    Ok(()) => {
                        println!("sent {} bytes", len);
                    }
                    Err(err) => panic!("{}", err),
                }
                std::thread::sleep(Duration::from_millis(100));
            }
        });
        Ok(())
    }

    fn on_error(&mut self, error: ws::Error) {
        println!("{:?}", error);
        //self.0.timeout(1000, self.0.token()).unwrap();
        //self.0.close(ws::CloseCode::Abnormal).unwrap();
    }
}

fn main() {
    // Setup logging
    env_logger::init();

    listen("127.0.0.1:3012", |out| Connection(out)).unwrap();
}

Python client:

from websocket import create_connection
ws = create_connection("ws://127.0.0.1:3012/")

ws.send("hello")

print("Sent")
print("Receiving...")

total_length = 0
while True:
    msg =  ws.recv()
    length = len(msg)
    total_length += length
    print("total bytes received: %s (%sMb)" % (total_length, total_length / 1024 / 1024))

After some time WS Error <Capacity>: Reached the limit of the output buffer for the connection. appears on the server side and we can see that connection is not closed (as I would expect).

As far as I understand it happens because connection.error() resets events to empty, so the socket is never waken up again, therefore check_active never runs and connection is never dropped.
This problem can be worked around using timeout() in on_error callback but I'm not sure if it's a good idea to put this burden on the user.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant