Not able to receive 'Continued' status from waitpid using the nix crate - debugging

I'm experimenting with the nix crate in order to debug child processes. I would like to receive events when the child process stops, continues and exits. Stoppages and exits are reported using the waitpid function. I'm having trouble receiving the continued status though.
I tried to convert my code to a minimum reproduceable example and hoping someone is able to spot the problem.
fn main() {
// fork here
let res = unsafe { fork().unwrap() };
if res.is_child() {
traceme().unwrap();
unsafe {
breakpoint();
}
} else {
let status = waitpid(Pid::from_raw(-1), Some(WaitPidFlag::WCONTINUED)).unwrap();
let pid = status.pid().unwrap();
println!("{:?}", status);
println!("Calling continue....");
cont(pid, None).unwrap();
println!("{:?}", waitpid(Pid::from_raw(-1), None).unwrap());
}
}
is producing the following output:
Stopped(Pid(28411), SIGTRAP)
Calling continue....
Exited(Pid(28411), 0)

Related

Error while trying to get PID with FindWindowA and GetWindowThreadProcessId

I'm trying to get the PID of a program in rust using the Windows crate, with the FindWindowA and GetWindowThreadProcessId functions. My problem is that GetWindowThreadProcessId fails with error 1400.
fn main(){
unsafe{
let process_name: PCSTR = windows::s!("ac_client.exe");
let window = windows::Win32::UI::WindowsAndMessaging::FindWindowA(None, process_name);
let error = windows::Win32::Foundation::GetLastError();
println!(" {:?}", error); //0
let mut pId= 0;
windows::Win32::UI::WindowsAndMessaging::GetWindowThreadProcessId(window, Some(&mut pId));
let error = windows::Win32::Foundation::GetLastError();
println!("{:?}", error); // 1400
}
}
error 1400: ERROR_INVALID_WINDOW_HANDLE Invalid window handle.
It seems that you used a wrong window handle. I suggest you could try to check the window handle. And you should make sure that the thread is valid before you call the GetWindowThreadProcessId.

detecting crashes of a std::packaged_task

I want to detect if a packaged task successfully completes, but have a few edge cases when errors in the task cause the thread to crash (from some 3rd party codes). In these cases no exceptions are caught by the below code and I am unable to tell that the thread crashed. The future_status is set as ready upon crash; however, if I try to get the result with .get() before I join the thread, the future will abort after internally calling _M_state->wait. Internally I can see that the future's _M_state._M_result is filled with garbage.
Can anyone think of how to determine if the task has successfully completed?
bool success = true;
try
{
std::packaged_task<int()> pTask(std::bind(&Method, pointerToObject, stuff));
std::future<int> ftr = pTask.get_future();
std::thread processingThread(std::move(pTask));
std::future_status status;
do
{
if (!ftr.valid()) throw std::future_error(std::future_errc::no_state);
status = ftr.wait_for(std::chrono::milliseconds(10));
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
} while (status != std::future_status::ready);
processingThread.join();
}
catch (std::future_error const&) success=false;
catch (std::exception const&) success=false;
end

How to read one single char in Rust? [duplicate]

I want to run an executable that blocks on stdin and when a key is pressed that same character is printed immediately without Enter having to be pressed.
How can I read one character from stdin without having to hit Enter? I started with this example:
fn main() {
println!("Type something!");
let mut line = String::new();
let input = std::io::stdin().read_line(&mut line).expect("Failed to read line");
println!("{}", input);
}
I looked through the API and tried replacing read_line() with bytes(), but everything I try requires me to hit Enter before read occurs.
This question was asked for C/C++, but there seems to be no standard way to do it: Capture characters from standard input without waiting for enter to be pressed
It might not be doable in Rust considering it's not simple in C/C++.
While #Jon's solution using ncurses works, ncurses clears the screen by design. I came up with this solution that uses the termios crate for my little project to learn Rust. The idea is to modify ECHO and ICANON flags by accessing tcsetattr through termios bindings.
extern crate termios;
use std::io;
use std::io::Read;
use std::io::Write;
use termios::{Termios, TCSANOW, ECHO, ICANON, tcsetattr};
fn main() {
let stdin = 0; // couldn't get std::os::unix::io::FromRawFd to work
// on /dev/stdin or /dev/tty
let termios = Termios::from_fd(stdin).unwrap();
let mut new_termios = termios.clone(); // make a mutable copy of termios
// that we will modify
new_termios.c_lflag &= !(ICANON | ECHO); // no echo and canonical mode
tcsetattr(stdin, TCSANOW, &mut new_termios).unwrap();
let stdout = io::stdout();
let mut reader = io::stdin();
let mut buffer = [0;1]; // read exactly one byte
print!("Hit a key! ");
stdout.lock().flush().unwrap();
reader.read_exact(&mut buffer).unwrap();
println!("You have hit: {:?}", buffer);
tcsetattr(stdin, TCSANOW, & termios).unwrap(); // reset the stdin to
// original termios data
}
One advantage of reading a single byte is capturing arrow keys, ctrl etc. Extended F-keys are not captured (although ncurses can capture these).
This solution is intended for UNIX-like platforms. I have no experience with Windows, but according to this forum perhaps something similar can be achieved using SetConsoleMode in Windows.
Use one of the 'ncurses' libraries now available, for instance this one.
Add the dependency in Cargo
[dependencies]
ncurses = "5.86.0"
and include in main.rs:
extern crate ncurses;
use ncurses::*; // watch for globs
Follow the examples in the library to initialize ncurses and wait for single character input like this:
initscr();
/* Print to the back buffer. */
printw("Hello, world!");
/* Update the screen. */
refresh();
/* Wait for a key press. */
getch();
/* Terminate ncurses. */
endwin();
You can also use termion, but you will have to enable the raw TTY mode which changes the behavior of stdout as well. See the example below (tested with Rust 1.34.0). Note that internally, it also wraps the termios UNIX API.
Cargo.toml
[dependencies]
termion = "1.5.2"
main.rs
use std::io;
use std::io::Write;
use std::thread;
use std::time;
use termion;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
fn main() {
// Set terminal to raw mode to allow reading stdin one key at a time
let mut stdout = io::stdout().into_raw_mode().unwrap();
// Use asynchronous stdin
let mut stdin = termion::async_stdin().keys();
loop {
// Read input (if any)
let input = stdin.next();
// If a key was pressed
if let Some(Ok(key)) = input {
match key {
// Exit if 'q' is pressed
termion::event::Key::Char('q') => break,
// Else print the pressed key
_ => {
write!(
stdout,
"{}{}Key pressed: {:?}",
termion::clear::All,
termion::cursor::Goto(1, 1),
key
)
.unwrap();
stdout.lock().flush().unwrap();
}
}
}
thread::sleep(time::Duration::from_millis(50));
}
}
Here's a lightweight solution only using the libc crate based some code from the console crate:
fn setup_raw_terminal() -> io::Result<()> {
unsafe {
let tty;
let fd = if libc::isatty(libc::STDIN_FILENO) == 1 {
libc::STDIN_FILENO
} else {
tty = fs::File::open("/dev/tty")?;
tty.as_raw_fd()
};
let mut ptr = core::mem::MaybeUninit::uninit();
if libc::tcgetattr(fd, ptr.as_mut_ptr()) == 0 {
let mut termios = ptr.assume_init();
let c_oflag = termios.c_oflag;
libc::cfmakeraw(&mut termios);
termios.c_oflag = c_oflag;
if libc::tcsetattr(fd, libc::TCSADRAIN, &termios) == 0 {
return Ok(());
}
}
}
Err(io::Error::last_os_error())
}
It needs to be called before reading stdin:
let mut buf = [0u8; 1024];
let mut stdin = io::stdin();
setup_raw_terminal()?;
loop {
let size = stdin.read(&mut buf)?;
let data = &buf[0..size];
println!("stdin data: {}", data);
}

Automatically Resume a Suspended Windows Process

I'm trying to write a windows batch file in order to resume a windows process that gets Suspended. I'm using pssuspend (from pstools) to resume the process. However, I'm trying to write windows batch file script that will continually get the status of a process (e.g. myExe.exe). If the script is not suspended, I would like for it to keep checking if it is suspended. If it is suspended, I would like it to run the pssuspend code. I'm unsure how to obtain the Suspend status. So far I have this:
if myExe.exe == "Suspend" (
pssuspend -r myExe.exe
suspend_fix.bat
) else (
suspend_fix.bat
)
Thanks for your help!
Windows services (that are created with the right attributes) can be suspended, but I am not sure how an executable can be suspended, or what exactly you mean by that.
If you mean that the program has been stopped, and when it does, you want to restart it, then here are a couple of code blocks that I have used to determine if a program is running:
1) by checking to see if the exe name exists, i.e., is running.
By the way, I recommend this one from my interpretation of your post:
BOOL ExeExists(char *exe)
{
HANDLE pss = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(pe);
if (Process32First(pss, &pe))
{
do
{
if (strstr(pe.szExeFile,exe))
{
CloseHandle(pss);
return TRUE;
}
}
while(Process32Next(pss, &pe));
}
CloseHandle(pss);
return FALSE;
}
2) by checking to see if the PID exists
BOOL PidExists(int pid)
{
HANDLE pss = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(pe);
if (Process32First(pss, &pe))
{
do
{
if (pe.th32ProcessID == pid)
{
CloseHandle(pss);
return TRUE;
}
}
while(Process32Next(pss, &pe));
}
CloseHandle(pss);
return FALSE;
}
By the way this is used to get the process ID (it is defined in winbase.h)
of the application making the call.
int GetProcessIdApp(void)
{
return GetProcessId(GetCurrentProcess());//defined in WinBase.h
}
Inside WinBase.h
WINBASEAPI
DWORD
WINAPI
GetProcessId(
__in HANDLE Process
);
In my scenario, An application broadcasts its PID at start up, such that
my monitoring program (the Windows service) can read it, then use it to make an ongoing determination of the application's status. If the app is discovered to be dead, and if other criteria indicate it should still be running, my service will start it back up.

closing std::os::Pipe in a simple user written shell in Rust

I am trying to write a shell using Rust. Currently, I am implementing the pipe | function.
So I split the user input by | into a vector of programs. For the programs, I spawn a process if is not the last program in the vector. If it is the last one, I create the process and wait for it to finish.
Setting up the pipes:
let mut channels: ~[std::os::Pipe] = ~[];
for _ in range(0, progs.len()) {
channels.push(std::os::pipe());
}
Set the input and output FILENO
for i in range(0, progs.len()) {
let mut in_chan = libc::STDIN_FILENO;
let mut out_chan = libc::STDOUT_FILENO;
if i == 0 {
out_chan = channels[i].out;
}
if i > 0 {
in_chan = channels[i-1].input;
out_chan = channels[i].out;
}
if i == progs.len() - 1 {
out_chan = libc::STDOUT_FILENO;
}
}
Spawn the processes:
for i in range(0, progs.len()) {
if i == progs.len() - 1 {
let proc_run = run::Process::new(program, argv, run::ProcessOptions {
env: None,
dir: None,
in_fd: Some(in_chan),
out_fd: Some(out_chan),
err_fd: Some(libc::STDERR_FILENO)
});
proc_run.unwrap().finish();
}
else {
do spawn {
let proc_run = run::Process::new(program, argv, run::ProcessOptions {
env: None,
dir: None,
in_fd: Some(in_chan),
out_fd: Some(out_chan),
err_fd: Some(libc::STDERR_FILENO)
});
proc_run.unwrap().finish();
}
}
}
I tried to run this with a simple C++ program:
#include <iostream>
using namespace std;
int main() {
int readNo;
while(cin >> readNo) {
cout << readNo+1 << endl;
}
return 0;
}
I ran with ./a.out | ./a.out
It seems to me that the pipes are working (1 => 3, 2 => 4 etc) but when I close the stdin with ctrl + d. Only the first process (the process spawned first) finishes. The rest are still running. What is wrong here and how shall I tell the rest of the processes to terminate?
EDIT:
I can do this with blocking process for all programs in the vector:
for i in range(0, progs.len()) {
let proc_run = run::Process::new(program, argv, run::ProcessOptions {
env: None,
dir: None,
in_fd: Some(in_chan),
out_fd: Some(out_chan),
err_fd: Some(libc::STDERR_FILENO)
});
proc_run.unwrap().finish();
}
But this is not what a "shell" does, it should be non-blocking between the processes. When I enter 1 into stdin, it should spit out 3 immediately.
Any help on any parts is appreciated!
Have you tried closing the stdout descriptor when each process ends?
e.g.
extern crate libc;
...
proc_run.unwrap().finish();
libc::unistd::close(out_chan)
The pipe is owned by the Rust Shell program, not the exited process, so when it exits, the pipe remains open. Closing it yourself, should close stdin on the following process.

Resources