打印!同时调用时发生恐慌

Max*_*son 2 rust

我正在尝试处理一些 *nix 信号并具有以下代码:

// nix = "0.8.0"
extern crate nix;

use nix::sys::signal::{SaFlags, SigAction, sigaction, SIGINT, SigSet};
use nix::sys::signal::SigHandler::Handler;

extern fn interrupted(_:i32) {
    println!("Interrupted");
}

fn main() {
    let sigact = SigAction::new(Handler(interrupted), SaFlags::empty(), SigSet::thread_get_mask().unwrap());

    if let Err(_) = unsafe { sigaction(SIGINT, &sigact) } {
        println!("Failed to register handler");
        std::process::exit(1);
    }

    loop {
        println!("Hello");
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为println!()可以同时调用,但是当我中断时此代码总是出现恐慌

// nix = "0.8.0"
extern crate nix;

use nix::sys::signal::{SaFlags, SigAction, sigaction, SIGINT, SigSet};
use nix::sys::signal::SigHandler::Handler;

extern fn interrupted(_:i32) {
    println!("Interrupted");
}

fn main() {
    let sigact = SigAction::new(Handler(interrupted), SaFlags::empty(), SigSet::thread_get_mask().unwrap());

    if let Err(_) = unsafe { sigaction(SIGINT, &sigact) } {
        println!("Failed to register handler");
        std::process::exit(1);
    }

    loop {
        println!("Hello");
    }
}
Run Code Online (Sandbox Code Playgroud)

的文档println!()没有具体提到并发执行的任何恐慌,只是说它在无法写入标准输出时会出现恐慌。我对这种恐慌有点困惑,因为println!()从循环中的多个线程调用工作正常。

问题是println!()线程安全的,但在同一线程上不安全,即,当println!()in的第一个实例被中断并且在同一线程上调用main第二个实例时,会违反一些线程局部静态依赖关系,或者如何interrupted我想象的是这个?

Fra*_*gné 5

问题是println!()线程安全的,但在同一线程上不安全,即,当println!()in的第一个实例被中断并且在同一线程上调用main第二个实例时,会违反一些线程本地静态依赖关系[... interrupted]?

是的,差不多是这样。

println!()宏委托给print!(),后者调用std::io::_print,后者print_to通过&LOCAL_STDOUT作为参数传递来调用。LOCAL_STDOUT定义如下:

/// Stdout used by print! and println! macros
thread_local! {
    static LOCAL_STDOUT: RefCell<Option<Box<Write + Send>>> = {
        RefCell::new(None)
    }
}
Run Code Online (Sandbox Code Playgroud)

您看到的恐慌RefCell来自LOCAL_STDOUT. 信号处理程序在接收信号的线程上运行。因此,当发出信号时,信号处理程序可以在RefCell可变借用的同时运行。由于RefCell一次只允许一个可变借用,因此尝试println!()在信号处理程序中使用可能会出现恐慌。