Repository: tokio-rs/tokio
File: tokio/src/net/unix/listener.rs (Rust)

Code before:
    ///
    /// # Panics
    ///
    /// This function panics if it is not called from within a runtime with
    /// IO enabled.
    ///
    /// The runtime is usually set implicitly when this function is called
    /// from a future driven by a tokio runtime, otherwise runtime can be set
    /// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
    #[track_caller]
    pub fn bind<P>(path: P) -> io::Result<UnixListener>
    where
        P: AsRef<Path>,
    {
        let listener = mio::net::UnixListener::bind(path)?;
        let io = PollEvented::new(listener)?;
        Ok(UnixListener { io })
    }

    /// Creates new [`UnixListener`] from a [`std::os::unix::net::UnixListener`].
    ///
    /// This function is intended to be used to wrap a `UnixListener` from the
    /// standard library in the Tokio equivalent.
    ///
    /// # Notes
    ///
    /// The caller is responsible for ensuring that the listener is in
    /// non-blocking mode. Otherwise all I/O operations on the listener
    /// will block the thread, which will cause unexpected behavior.
    /// Non-blocking mode can be set using [`set_nonblocking`].
    ///
    /// [`set_nonblocking`]: std::os::unix::net::UnixListener::set_nonblocking
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use tokio::net::UnixListener;
    /// use std::os::unix::net::UnixListener as StdUnixListener;
    /// # use std::error::Error;
    ///
    /// # async fn dox() -> Result<(), Box<dyn Error>> {
    /// let std_listener = StdUnixListener::bind("/path/to/the/socket")?;
    /// std_listener.set_nonblocking(true)?;
    /// let listener = UnixListener::from_std(std_listener)?;
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// # Panics
    ///
    /// This function panics if it is not called from within a runtime with

Review comment (bug):
I think there might a bug here.
The leading '\0' should not be passed to the StdSocketAddr::from_abstract_name() because this way there will be two leading NUL chars in the final name (i.e. `\0\0...`).

See https://github.com/rust-lang/rust/blob/1.89.0/library/std/src/os/unix/net/addr.rs#L273-L285

Here the `addr` is initialized with `mem::zeroed()` and later the passed name is copied to the `ptr + 1`:
```rust
crate::ptr::copy_nonoverlapping(
                name.as_ptr(),
                addr.sun_path.as_mut_ptr().add(1) as *mut u8,
                name.len(),
            );
```
So, there are two NULs - one from zeroed() and another from `name`.

Code after:
    pub(crate) fn new(listener: mio::net::UnixListener) -> io::Result<UnixListener> {
        let io = PollEvented::new(listener)?;
        Ok(UnixListener { io })
    }

    /// Creates a new `UnixListener` bound to the specified path.
    ///
    /// # Panics
    ///
    /// This function panics if it is not called from within a runtime with
    /// IO enabled.
    ///
    /// The runtime is usually set implicitly when this function is called
    /// from a future driven by a tokio runtime, otherwise runtime can be set
    /// explicitly with [`Runtime::enter`](crate::runtime::Runtime::enter) function.
    #[track_caller]
    pub fn bind<P>(path: P) -> io::Result<UnixListener>
    where
        P: AsRef<Path>,
    {
        // For now, we handle abstract socket paths on linux here.
        #[cfg(any(target_os = "linux", target_os = "android"))]
        let addr = {
            let os_str_bytes = path.as_ref().as_os_str().as_bytes();
            if os_str_bytes.starts_with(b"\0") {
                StdSocketAddr::from_abstract_name(os_str_bytes)?
            } else {
                StdSocketAddr::from_pathname(path)?
            }
        };
        #[cfg(not(any(target_os = "linux", target_os = "android")))]
        let addr = StdSocketAddr::from_pathname(path)?;

        let listener = mio::net::UnixListener::bind_addr(&addr)?;
        let io = PollEvented::new(listener)?;
        Ok(UnixListener { io })
    }

    /// Creates new [`UnixListener`] from a [`std::os::unix::net::UnixListener`].
    ///
    /// This function is intended to be used to wrap a `UnixListener` from the
    /// standard library in the Tokio equivalent.
    ///
    /// # Notes
    ///
    /// The caller is responsible for ensuring that the listener is in
    /// non-blocking mode. Otherwise all I/O operations on the listener
    /// will block the thread, which will cause unexpected behavior.
    /// Non-blocking mode can be set using [`set_nonblocking`].
    ///
    /// [`set_nonblocking`]: std::os::unix::net::UnixListener::set_nonblocking