mirror of
https://github.com/asciinema/asciinema.git
synced 2025-12-15 19:28:00 +01:00
Upgrade deps
This commit is contained in:
1694
Cargo.lock
generated
1694
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
34
Cargo.toml
34
Cargo.toml
@@ -14,38 +14,38 @@ rust-version = "1.75.0"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.75"
|
anyhow = "1.0.98"
|
||||||
nix = { version = "0.27", features = [ "fs", "term", "process", "signal" ] }
|
nix = { version = "0.30", features = ["fs", "term", "process", "signal", "poll"] }
|
||||||
termion = "3.0.0"
|
termion = "3.0.0"
|
||||||
serde = { version = "1.0.189", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
serde_json = "1.0.107"
|
serde_json = "1.0.140"
|
||||||
clap = { version = "4.5.37", features = ["derive"] }
|
clap = { version = "4.5.37", features = ["derive"] }
|
||||||
signal-hook = { version = "0.3.17", default-features = false }
|
signal-hook = { version = "0.3.17", default-features = false }
|
||||||
uuid = { version = "1.6.1", features = ["v4"] }
|
uuid = { version = "1.6.1", features = ["v4"] }
|
||||||
reqwest = { version = "0.12.8", default-features = false, features = ["blocking", "rustls-tls-native-roots", "multipart", "gzip", "json"] }
|
reqwest = { version = "0.12.15", default-features = false, features = ["blocking", "rustls-tls-native-roots", "multipart", "gzip", "json"] }
|
||||||
rustyline = "13.0.0"
|
rustyline = "13.0.0"
|
||||||
config = { version = "0.14.0", default-features = false, features = ["toml", "ini"] }
|
config = { version = "0.15.11", default-features = false, features = ["toml", "ini"] }
|
||||||
which = "6.0.0"
|
which = "6.0.3"
|
||||||
tempfile = "3.9.0"
|
tempfile = "3.9.0"
|
||||||
scraper = { version = "0.19.0", default-features = false }
|
scraper = { version = "0.23.1", default-features = false }
|
||||||
avt = "0.15.1"
|
avt = "0.15.1"
|
||||||
axum = { version = "0.7.7", default-features = false, features = ["http1", "ws"] }
|
axum = { version = "0.8.4", default-features = false, features = ["http1", "ws"] }
|
||||||
tokio = { version = "1.35.1", features = ["full"] }
|
tokio = { version = "1.44.2", features = ["full"] }
|
||||||
futures-util = "0.3.30"
|
futures-util = "0.3.31"
|
||||||
tokio-stream = { version = "0.1.14", features = ["sync"] }
|
tokio-stream = { version = "0.1.17", features = ["sync"] }
|
||||||
rust-embed = "8.2.0"
|
rust-embed = "8.2.0"
|
||||||
mime_guess = "2.0.4"
|
mime_guess = "2.0.4"
|
||||||
tower-http = { version = "0.5.1", features = ["trace"] }
|
tower-http = { version = "0.6.2", features = ["trace"] }
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.41"
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||||
rgb = "0.8.37"
|
rgb = "0.8.37"
|
||||||
url = "2.5.0"
|
url = "2.5.0"
|
||||||
tokio-tungstenite = { version = "0.24.0", features = ["rustls-tls-native-roots"] }
|
tokio-tungstenite = { version = "0.26.2", features = ["rustls-tls-native-roots"] }
|
||||||
rustls = { version = "0.23.15", default-features = false, features = ["aws_lc_rs"] }
|
rustls = { version = "0.23.26", default-features = false, features = ["aws_lc_rs"] }
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
tokio-util = "0.7.10"
|
tokio-util = "0.7.10"
|
||||||
chrono = "0.4.38"
|
chrono = "0.4.38"
|
||||||
hostname = "0.4.0"
|
hostname = "0.4.1"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
clap = { version = "4.5.37", features = ["derive"] }
|
clap = { version = "4.5.37", features = ["derive"] }
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use core::future::{self, Future};
|
use core::future::{self, Future};
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -238,12 +237,12 @@ fn ws_result(m: Result<Vec<u8>, BroadcastStreamRecvError>) -> anyhow::Result<Mes
|
|||||||
fn close_message() -> Message {
|
fn close_message() -> Message {
|
||||||
Message::Close(Some(CloseFrame {
|
Message::Close(Some(CloseFrame {
|
||||||
code: CloseCode::Normal,
|
code: CloseCode::Normal,
|
||||||
reason: Cow::from("ended"),
|
reason: "ended".into(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ping_stream() -> impl Stream<Item = Message> {
|
fn ping_stream() -> impl Stream<Item = Message> {
|
||||||
IntervalStream::new(interval(Duration::from_secs(PING_INTERVAL)))
|
IntervalStream::new(interval(Duration::from_secs(PING_INTERVAL)))
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.map(|_| Message::Ping(vec![]))
|
.map(|_| Message::Ping(vec![].into()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::os::fd::RawFd;
|
use std::os::fd::AsFd;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
pub fn set_non_blocking(fd: &RawFd) -> Result<(), io::Error> {
|
pub fn set_non_blocking<T: AsFd>(fd: &T) -> Result<(), io::Error> {
|
||||||
use nix::fcntl::{fcntl, FcntlArg::*, OFlag};
|
use nix::fcntl::{fcntl, FcntlArg::*, OFlag};
|
||||||
|
|
||||||
let flags = fcntl(*fd, F_GETFL)?;
|
let flags = fcntl(fd, F_GETFL)?;
|
||||||
let mut oflags = OFlag::from_bits_truncate(flags);
|
let mut oflags = OFlag::from_bits_truncate(flags);
|
||||||
oflags |= OFlag::O_NONBLOCK;
|
oflags |= OFlag::O_NONBLOCK;
|
||||||
fcntl(*fd, F_SETFL(oflags))?;
|
fcntl(fd, F_SETFL(oflags))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,15 +145,16 @@ fn open_recording(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_input<T: Tty>(tty: &mut T, timeout: i64) -> Result<Option<Vec<u8>>> {
|
fn read_input<T: Tty>(tty: &mut T, timeout: i64) -> Result<Option<Vec<u8>>> {
|
||||||
let nfds = Some(tty.as_fd().as_raw_fd() + 1);
|
let tty_fd = tty.as_fd();
|
||||||
|
let nfds = Some(tty_fd.as_raw_fd() + 1);
|
||||||
let mut rfds = FdSet::new();
|
let mut rfds = FdSet::new();
|
||||||
rfds.insert(tty);
|
rfds.insert(tty_fd);
|
||||||
let timeout = TimeSpec::microseconds(timeout);
|
let timeout = TimeSpec::microseconds(timeout);
|
||||||
let mut input: Vec<u8> = Vec::new();
|
let mut input: Vec<u8> = Vec::new();
|
||||||
|
|
||||||
pselect(nfds, &mut rfds, None, None, &timeout, None)?;
|
pselect(nfds, &mut rfds, None, None, &timeout, None)?;
|
||||||
|
|
||||||
if rfds.contains(tty) {
|
if rfds.contains(tty_fd) {
|
||||||
let mut buf = [0u8; 1024];
|
let mut buf = [0u8; 1024];
|
||||||
|
|
||||||
while let Ok(n) = tty.read(&mut buf) {
|
while let Ok(n) = tty.read(&mut buf) {
|
||||||
|
|||||||
64
src/pty.rs
64
src/pty.rs
@@ -5,7 +5,7 @@ use std::fs::File;
|
|||||||
use std::io::{self, ErrorKind, Read, Write};
|
use std::io::{self, ErrorKind, Read, Write};
|
||||||
use std::os::fd::AsFd;
|
use std::os::fd::AsFd;
|
||||||
use std::os::fd::{BorrowedFd, OwnedFd};
|
use std::os::fd::{BorrowedFd, OwnedFd};
|
||||||
use std::os::unix::io::{AsRawFd, FromRawFd};
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
@@ -14,7 +14,7 @@ use nix::libc::EIO;
|
|||||||
use nix::sys::select::{select, FdSet};
|
use nix::sys::select::{select, FdSet};
|
||||||
use nix::sys::signal::{self, kill, Signal};
|
use nix::sys::signal::{self, kill, Signal};
|
||||||
use nix::sys::wait::{self, WaitPidFlag, WaitStatus};
|
use nix::sys::wait::{self, WaitPidFlag, WaitStatus};
|
||||||
use nix::unistd::{self, ForkResult};
|
use nix::unistd;
|
||||||
use nix::{libc, pty};
|
use nix::{libc, pty};
|
||||||
use signal_hook::consts::{SIGALRM, SIGCHLD, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGWINCH};
|
use signal_hook::consts::{SIGALRM, SIGCHLD, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGWINCH};
|
||||||
use signal_hook::SigId;
|
use signal_hook::SigId;
|
||||||
@@ -46,13 +46,13 @@ pub fn exec<S: AsRef<str>, T: Tty, H: Handler, R: HandlerStarter<H>>(
|
|||||||
let mut handler = handler_starter.start(winsize.into(), tty.get_theme());
|
let mut handler = handler_starter.start(winsize.into(), tty.get_theme());
|
||||||
let result = unsafe { pty::forkpty(Some(&winsize), None) }?;
|
let result = unsafe { pty::forkpty(Some(&winsize), None) }?;
|
||||||
|
|
||||||
match result.fork_result {
|
match result {
|
||||||
ForkResult::Parent { child } => {
|
pty::ForkptyResult::Parent { child, master } => {
|
||||||
handle_parent(result.master, child, tty, &mut handler, epoch)
|
handle_parent(master, child, tty, &mut handler, epoch)
|
||||||
.map(|code| (code, handler.stop()))
|
.map(|code| (code, handler.stop()))
|
||||||
}
|
}
|
||||||
|
|
||||||
ForkResult::Child => {
|
pty::ForkptyResult::Child => {
|
||||||
handle_child(command, extra_env)?;
|
handle_child(command, extra_env)?;
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ fn copy<T: Tty, H: Handler>(
|
|||||||
let sigalrm_fd = SignalFd::open(SIGALRM)?;
|
let sigalrm_fd = SignalFd::open(SIGALRM)?;
|
||||||
let sigchld_fd = SignalFd::open(SIGCHLD)?;
|
let sigchld_fd = SignalFd::open(SIGCHLD)?;
|
||||||
|
|
||||||
set_non_blocking(&master_raw_fd)?;
|
set_non_blocking(&master)?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let master_fd = master.as_fd();
|
let master_fd = master.as_fd();
|
||||||
@@ -116,25 +116,25 @@ fn copy<T: Tty, H: Handler>(
|
|||||||
let mut rfds = FdSet::new();
|
let mut rfds = FdSet::new();
|
||||||
let mut wfds = FdSet::new();
|
let mut wfds = FdSet::new();
|
||||||
|
|
||||||
rfds.insert(&tty_fd);
|
rfds.insert(tty_fd);
|
||||||
rfds.insert(&sigwinch_fd);
|
rfds.insert(sigwinch_fd.as_fd());
|
||||||
rfds.insert(&sigint_fd);
|
rfds.insert(sigint_fd.as_fd());
|
||||||
rfds.insert(&sigterm_fd);
|
rfds.insert(sigterm_fd.as_fd());
|
||||||
rfds.insert(&sigquit_fd);
|
rfds.insert(sigquit_fd.as_fd());
|
||||||
rfds.insert(&sighup_fd);
|
rfds.insert(sighup_fd.as_fd());
|
||||||
rfds.insert(&sigalrm_fd);
|
rfds.insert(sigalrm_fd.as_fd());
|
||||||
rfds.insert(&sigchld_fd);
|
rfds.insert(sigchld_fd.as_fd());
|
||||||
|
|
||||||
if !master_closed {
|
if !master_closed {
|
||||||
rfds.insert(&master_fd);
|
rfds.insert(master_fd);
|
||||||
|
|
||||||
if !input.is_empty() {
|
if !input.is_empty() {
|
||||||
wfds.insert(&master_fd);
|
wfds.insert(master_fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !output.is_empty() {
|
if !output.is_empty() {
|
||||||
wfds.insert(&tty_fd);
|
wfds.insert(tty_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = select(None, &mut rfds, &mut wfds, None, None) {
|
if let Err(e) = select(None, &mut rfds, &mut wfds, None, None) {
|
||||||
@@ -145,17 +145,17 @@ fn copy<T: Tty, H: Handler>(
|
|||||||
bail!(e);
|
bail!(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
let master_read = rfds.contains(&master_fd);
|
let master_read = rfds.contains(master_fd);
|
||||||
let master_write = wfds.contains(&master_fd);
|
let master_write = wfds.contains(master_fd);
|
||||||
let tty_read = rfds.contains(&tty_fd);
|
let tty_read = rfds.contains(tty_fd);
|
||||||
let tty_write = wfds.contains(&tty_fd);
|
let tty_write = wfds.contains(tty_fd);
|
||||||
let sigwinch_read = rfds.contains(&sigwinch_fd);
|
let sigwinch_read = rfds.contains(sigwinch_fd.as_fd());
|
||||||
let sigint_read = rfds.contains(&sigint_fd);
|
let sigint_read = rfds.contains(sigint_fd.as_fd());
|
||||||
let sigterm_read = rfds.contains(&sigterm_fd);
|
let sigterm_read = rfds.contains(sigterm_fd.as_fd());
|
||||||
let sigquit_read = rfds.contains(&sigquit_fd);
|
let sigquit_read = rfds.contains(sigquit_fd.as_fd());
|
||||||
let sighup_read = rfds.contains(&sighup_fd);
|
let sighup_read = rfds.contains(sighup_fd.as_fd());
|
||||||
let sigalrm_read = rfds.contains(&sigalrm_fd);
|
let sigalrm_read = rfds.contains(sigalrm_fd.as_fd());
|
||||||
let sigchld_read = rfds.contains(&sigchld_fd);
|
let sigchld_read = rfds.contains(sigchld_fd.as_fd());
|
||||||
|
|
||||||
if master_read {
|
if master_read {
|
||||||
while let Some(n) = read_non_blocking(&mut master, &mut buf)? {
|
while let Some(n) = read_non_blocking(&mut master, &mut buf)? {
|
||||||
@@ -347,12 +347,10 @@ impl SignalFd {
|
|||||||
let (rx, tx) = unistd::pipe()?;
|
let (rx, tx) = unistd::pipe()?;
|
||||||
set_non_blocking(&rx)?;
|
set_non_blocking(&rx)?;
|
||||||
set_non_blocking(&tx)?;
|
set_non_blocking(&tx)?;
|
||||||
let rx = unsafe { OwnedFd::from_raw_fd(rx) };
|
|
||||||
let tx = unsafe { OwnedFd::from_raw_fd(tx) };
|
|
||||||
|
|
||||||
let sigid = unsafe {
|
let sigid = unsafe {
|
||||||
signal_hook::low_level::register(signal, move || {
|
signal_hook::low_level::register(signal, move || {
|
||||||
let _ = unistd::write(tx.as_raw_fd(), &[0]);
|
let _ = unistd::write(&tx, &[0]);
|
||||||
})
|
})
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
@@ -362,7 +360,7 @@ impl SignalFd {
|
|||||||
fn flush(&self) {
|
fn flush(&self) {
|
||||||
let mut buf = [0; 256];
|
let mut buf = [0; 256];
|
||||||
|
|
||||||
while let Ok(n) = unistd::read(self.rx.as_raw_fd(), &mut buf) {
|
while let Ok(n) = unistd::read(&self.rx, &mut buf) {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use std::borrow::Cow;
|
|
||||||
use std::future;
|
use std::future;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
@@ -9,6 +8,7 @@ use axum::extract::State;
|
|||||||
use axum::http::{header, StatusCode, Uri};
|
use axum::http::{header, StatusCode, Uri};
|
||||||
use axum::response::IntoResponse;
|
use axum::response::IntoResponse;
|
||||||
use axum::routing::get;
|
use axum::routing::get;
|
||||||
|
use axum::serve::ListenerExt;
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
use futures_util::{sink, StreamExt};
|
use futures_util::{sink, StreamExt};
|
||||||
use rust_embed::RustEmbed;
|
use rust_embed::RustEmbed;
|
||||||
@@ -50,12 +50,15 @@ pub async fn serve(
|
|||||||
listener.local_addr().unwrap()
|
listener.local_addr().unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let listener = listener.tap_io(|tcp_stream| {
|
||||||
|
let _ = tcp_stream.set_nodelay(true);
|
||||||
|
});
|
||||||
|
|
||||||
axum::serve(
|
axum::serve(
|
||||||
listener,
|
listener,
|
||||||
app.into_make_service_with_connect_info::<SocketAddr>(),
|
app.into_make_service_with_connect_info::<SocketAddr>(),
|
||||||
)
|
)
|
||||||
.with_graceful_shutdown(signal)
|
.with_graceful_shutdown(signal)
|
||||||
.tcp_nodelay(true)
|
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,13 +126,13 @@ async fn close_socket(mut socket: WebSocket) {
|
|||||||
fn close_message(code: CloseCode, reason: &'static str) -> Message {
|
fn close_message(code: CloseCode, reason: &'static str) -> Message {
|
||||||
Message::Close(Some(CloseFrame {
|
Message::Close(Some(CloseFrame {
|
||||||
code,
|
code,
|
||||||
reason: Cow::from(reason),
|
reason: reason.into(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ws_result(m: Result<Vec<u8>, BroadcastStreamRecvError>) -> Result<Message, axum::Error> {
|
fn ws_result(m: Result<Vec<u8>, BroadcastStreamRecvError>) -> Result<Message, axum::Error> {
|
||||||
match m {
|
match m {
|
||||||
Ok(bytes) => Ok(Message::Binary(bytes)),
|
Ok(bytes) => Ok(Message::Binary(bytes.into())),
|
||||||
Err(e) => Err(axum::Error::new(e)),
|
Err(e) => Err(axum::Error::new(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/tty.rs
16
src/tty.rs
@@ -1,6 +1,6 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd};
|
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use nix::{
|
use nix::{
|
||||||
@@ -67,7 +67,7 @@ impl DevTty {
|
|||||||
.open("/dev/tty")?
|
.open("/dev/tty")?
|
||||||
.into_raw_mode()?;
|
.into_raw_mode()?;
|
||||||
|
|
||||||
crate::io::set_non_blocking(&file.as_raw_fd())?;
|
crate::io::set_non_blocking(&file)?;
|
||||||
|
|
||||||
Ok(Self { file })
|
Ok(Self { file })
|
||||||
}
|
}
|
||||||
@@ -78,23 +78,23 @@ impl DevTty {
|
|||||||
let mut query = &query[..];
|
let mut query = &query[..];
|
||||||
let mut response = Vec::new();
|
let mut response = Vec::new();
|
||||||
let mut buf = [0u8; 1024];
|
let mut buf = [0u8; 1024];
|
||||||
let fd = self.as_fd().as_raw_fd();
|
let fd = self.as_fd();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut timeout = TimeVal::new(0, 100_000);
|
let mut timeout = TimeVal::new(0, 100_000);
|
||||||
let mut rfds = FdSet::new();
|
let mut rfds = FdSet::new();
|
||||||
let mut wfds = FdSet::new();
|
let mut wfds = FdSet::new();
|
||||||
rfds.insert(self);
|
rfds.insert(fd);
|
||||||
|
|
||||||
if !query.is_empty() {
|
if !query.is_empty() {
|
||||||
wfds.insert(self);
|
wfds.insert(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
match select(None, &mut rfds, &mut wfds, None, &mut timeout) {
|
match select(None, &mut rfds, &mut wfds, None, &mut timeout) {
|
||||||
Ok(0) => break,
|
Ok(0) => break,
|
||||||
|
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
if rfds.contains(self) {
|
if rfds.contains(fd) {
|
||||||
let n = unistd::read(fd, &mut buf)?;
|
let n = unistd::read(fd, &mut buf)?;
|
||||||
response.extend_from_slice(&buf[..n]);
|
response.extend_from_slice(&buf[..n]);
|
||||||
let mut reversed = response.iter().rev();
|
let mut reversed = response.iter().rev();
|
||||||
@@ -124,7 +124,7 @@ impl DevTty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if wfds.contains(self) {
|
if wfds.contains(fd) {
|
||||||
let n = unistd::write(fd, query)?;
|
let n = unistd::write(fd, query)?;
|
||||||
query = &query[n..];
|
query = &query[n..];
|
||||||
}
|
}
|
||||||
@@ -239,8 +239,6 @@ pub struct NullTty {
|
|||||||
impl NullTty {
|
impl NullTty {
|
||||||
pub fn open() -> Result<Self> {
|
pub fn open() -> Result<Self> {
|
||||||
let (rx, tx) = unistd::pipe()?;
|
let (rx, tx) = unistd::pipe()?;
|
||||||
let rx = unsafe { OwnedFd::from_raw_fd(rx) };
|
|
||||||
let tx = unsafe { OwnedFd::from_raw_fd(tx) };
|
|
||||||
|
|
||||||
Ok(Self { tx, _rx: rx })
|
Ok(Self { tx, _rx: rx })
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user