`libc::signal` 用于 `impl` 方法
`libc::signal` for `impl` method
我想在发送 SIGUSR1
信号时调用 impl
方法。
考虑以下示例:
use libc::SIGUSR1;
use std::{thread, time};
struct Foo {
}
impl Foo {
fn show(&self) {
println!("Foo SIGNAL")
}
}
fn main() {
let foo = Foo {};
unsafe {
libc::signal(SIGUSR1, foo.show as usize);
}
loop{
println!("sleeping for 1 sec");
thread::sleep(time::Duration::from_secs(1));
}
}
我收到以下错误:
$ cargo run
Compiling hello_world v0.1.0 (/home/vasco/a)
error[E0615]: attempted to take value of method `show` on type `Foo`
--> src/main.rs:17:35
|
17 | libc::signal(SIGUSR1, foo.show as usize);
| ^^^^ method, not a field
|
help: use parentheses to call the method
|
17 | libc::signal(SIGUSR1, foo.show() as usize);
| ^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0615`.
error: could not compile `hello_world`
To learn more, run the command again with --verbose.
如果我听从建议 (libc::signal(SIGUSR1, foo.show() as usize);
):
$ cargo run
Compiling hello_world v0.1.0 (/home/vasco/a)
error[E0605]: non-primitive cast: `()` as `usize`
--> src/main.rs:17:31
|
17 | libc::signal(SIGUSR1, foo.show() as usize);
| ^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to previous error
For more information about this error, try `rustc --explain E0605`.
error: could not compile `hello_world`
To learn more, run the command again with --verbose.
使用正常函数按预期工作:
use libc::SIGUSR1;
use std::{thread, time};
fn show() {
println!("Foo SIGNAL")
}
fn main() {
unsafe {
libc::signal(SIGUSR1, show as usize);
}
let delay = time::Duration::from_secs(1);
loop{
println!("sleeping for 1 sec");
thread::sleep(delay);
}
}
有什么建议吗?
谢谢
感谢 Ahmed Masud:
use std::{thread, time};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
fn show() {
println!("SHOW");
}
fn main() {
loop {
// Declare bool, setting it to false
let term = Arc::new(AtomicBool::new(false));
// Ask signal_hook to set the term variable to true when the program receives a SIGUSR1 kill signal
signal_hook::flag::register(signal_hook::consts::SIGUSR1, Arc::clone(&term)).ok();
show();
while !term.load(Ordering::Relaxed) {
println!("sleeping for 1 sec");
thread::sleep(time::Duration::from_secs(1));
}
}
}
似乎按预期工作。
更新 1
上面的例子会每秒响应一次信号,不管什么时候触发信号,下面解决:
use std::io::Error;
use std::time::{SystemTime, UNIX_EPOCH};
use signal_hook::consts::signal::SIGUSR1;
use signal_hook::iterator::SignalsInfo;
use signal_hook::iterator::exfiltrator::WithOrigin;
fn show() {
let a = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis();
println!("show: {}", a);
}
fn mainloop() {
let handle = std::thread::spawn(|| {
loop {
let a = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis();
println!("main: {}", a);
std::thread::sleep(std::time::Duration::from_secs(1));
}
});
handle.join().unwrap();
}
fn main() -> Result<(), Error> {
// Subscribe to the SIGUSR1 signal
let sigs = vec![SIGUSR1];
let mut signals = SignalsInfo::<WithOrigin>::new(&sigs)?;
// Run the application in its own thread
mainloop();
// Consume all the incoming signals (this happens in "normal" Rust thread)
for info in &mut signals {
match info.signal {
SIGUSR1 => {
show();
}
_ => { // These are all the ones left
eprintln!("Terminating");
break;
}
}
}
Ok(())
}
$ cat Cargo.toml
[package]
...
[dependencies]
signal-hook = { version = "0.3", features = ["extended-siginfo"] }
我想在发送 SIGUSR1
信号时调用 impl
方法。
考虑以下示例:
use libc::SIGUSR1;
use std::{thread, time};
struct Foo {
}
impl Foo {
fn show(&self) {
println!("Foo SIGNAL")
}
}
fn main() {
let foo = Foo {};
unsafe {
libc::signal(SIGUSR1, foo.show as usize);
}
loop{
println!("sleeping for 1 sec");
thread::sleep(time::Duration::from_secs(1));
}
}
我收到以下错误:
$ cargo run
Compiling hello_world v0.1.0 (/home/vasco/a)
error[E0615]: attempted to take value of method `show` on type `Foo`
--> src/main.rs:17:35
|
17 | libc::signal(SIGUSR1, foo.show as usize);
| ^^^^ method, not a field
|
help: use parentheses to call the method
|
17 | libc::signal(SIGUSR1, foo.show() as usize);
| ^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0615`.
error: could not compile `hello_world`
To learn more, run the command again with --verbose.
如果我听从建议 (libc::signal(SIGUSR1, foo.show() as usize);
):
$ cargo run
Compiling hello_world v0.1.0 (/home/vasco/a)
error[E0605]: non-primitive cast: `()` as `usize`
--> src/main.rs:17:31
|
17 | libc::signal(SIGUSR1, foo.show() as usize);
| ^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to previous error
For more information about this error, try `rustc --explain E0605`.
error: could not compile `hello_world`
To learn more, run the command again with --verbose.
使用正常函数按预期工作:
use libc::SIGUSR1;
use std::{thread, time};
fn show() {
println!("Foo SIGNAL")
}
fn main() {
unsafe {
libc::signal(SIGUSR1, show as usize);
}
let delay = time::Duration::from_secs(1);
loop{
println!("sleeping for 1 sec");
thread::sleep(delay);
}
}
有什么建议吗?
谢谢
感谢 Ahmed Masud:
use std::{thread, time};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
fn show() {
println!("SHOW");
}
fn main() {
loop {
// Declare bool, setting it to false
let term = Arc::new(AtomicBool::new(false));
// Ask signal_hook to set the term variable to true when the program receives a SIGUSR1 kill signal
signal_hook::flag::register(signal_hook::consts::SIGUSR1, Arc::clone(&term)).ok();
show();
while !term.load(Ordering::Relaxed) {
println!("sleeping for 1 sec");
thread::sleep(time::Duration::from_secs(1));
}
}
}
似乎按预期工作。
更新 1
上面的例子会每秒响应一次信号,不管什么时候触发信号,下面解决:
use std::io::Error;
use std::time::{SystemTime, UNIX_EPOCH};
use signal_hook::consts::signal::SIGUSR1;
use signal_hook::iterator::SignalsInfo;
use signal_hook::iterator::exfiltrator::WithOrigin;
fn show() {
let a = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis();
println!("show: {}", a);
}
fn mainloop() {
let handle = std::thread::spawn(|| {
loop {
let a = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis();
println!("main: {}", a);
std::thread::sleep(std::time::Duration::from_secs(1));
}
});
handle.join().unwrap();
}
fn main() -> Result<(), Error> {
// Subscribe to the SIGUSR1 signal
let sigs = vec![SIGUSR1];
let mut signals = SignalsInfo::<WithOrigin>::new(&sigs)?;
// Run the application in its own thread
mainloop();
// Consume all the incoming signals (this happens in "normal" Rust thread)
for info in &mut signals {
match info.signal {
SIGUSR1 => {
show();
}
_ => { // These are all the ones left
eprintln!("Terminating");
break;
}
}
}
Ok(())
}
$ cat Cargo.toml
[package]
...
[dependencies]
signal-hook = { version = "0.3", features = ["extended-siginfo"] }