Yavor
Yavor

Reputation: 73

How to stop my tokio thread from blocking

I am writing a client for a Unix Domain Socket, which should listen for messages from a server, I got it to work after hours of researching (it shows 1-2 messages), but after that tokio crashes with the error: Error: Kind(WouldBlock), here is my code:

use std::env::{var, VarError};
use std::io::{self, Write};
use tokio::net::UnixStream;

#[tokio::main]
async fn main() -> io::Result<()> {
    let hypr_instance_sig = match var("HYPRLAND_INSTANCE_SIGNATURE") {
        Ok(var) => var,
        Err(VarError::NotPresent) => panic!("Is hyprland running?"),
        Err(VarError::NotUnicode(_)) => panic!("wtf no unicode?"),
    };

    let socket_path = format!("/tmp/hypr/{hypr_instance_sig}/.socket2.sock");

    let stream = UnixStream::connect(socket_path).await?;

    loop {
        stream.readable().await?;

        let mut buf = [0; 4096];
        stream.try_read(&mut buf)?;
        io::stdout().lock().write_all(&buf)?;
    }
}

Could someone please help me?

Upvotes: 1

Views: 1144

Answers (1)

Finomnis
Finomnis

Reputation: 22686

I fully agree with @Caesar's comment.

  • don't use try_read, use read instead
  • slice the buffer to the correct size after reading
  • check for 0 bytes read, which indicates that the end of the stream was reached
use std::env::{var, VarError};
use std::io::{self, Write};
use tokio::io::AsyncReadExt;
use tokio::net::UnixStream;

#[tokio::main]
async fn main() -> io::Result<()> {
    let hypr_instance_sig = match var("HYPRLAND_INSTANCE_SIGNATURE") {
        Ok(var) => var,
        Err(VarError::NotPresent) => panic!("Is hyprland running?"),
        Err(VarError::NotUnicode(_)) => panic!("wtf no unicode?"),
    };

    let socket_path = format!("/tmp/hypr/{hypr_instance_sig}/.socket2.sock");

    let mut stream = UnixStream::connect(socket_path).await?;

    let mut buf = [0; 4096];

    loop {
        let num_read = stream.read(&mut buf).await?;
        if num_read == 0 {
            break;
        }
        let buf = &buf[..num_read];
        io::stdout().lock().write_all(buf)?;
    }

    Ok(())
}

Disclaimer: I didn't test the code because I don't have the required socket file. It compiles, though.

Upvotes: 2

Related Questions