Using program arguments within a thread [duplicate] - multithreading

This question already has answers here:
Lifetime of variables passed to a new thread
(1 answer)
How can I pass a reference to a stack variable to a thread?
(1 answer)
Closed 3 years ago.
I am having issues passing command-line arguments into threads so have constructed this program which illustrates my issue.
use std::env;
use std::io::{self, Write};
use std::thread;
fn main() {
let stdout = io::stdout();
let args: Vec<String> = env::args().collect();
let arg = &args[1];
let thread = thread::spawn(move || {
writeln!(stdout.lock(), "argument was \"{}\"", arg).unwrap();
});
thread.join().unwrap();
}
However, the compiler gives me the following error when I try to compile this...
error[E0597]: `args` does not live long enough
--> main.rs:9:14
|
9 | let arg = &args[1];
| ^^^^ borrowed value does not live long enough
...
16 | }
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
I am unsure as to how to compile a program like this. I understand the the &str created by &args[1] does not have a static lifetime so cannot be passed into the thread. However, what options are there for passing in program arguments into a thread?

Related

How to use a Mutex to share writable memory? cannot move out of dereference of std::sync::MutexGuard [duplicate]

This question already has answers here:
Mutable borrow to object inside Mutex - how to refactor?
(2 answers)
Closed 10 months ago.
Code:
pub async fn start_orderbook_updater(websocket: Arc<Mutex<Ws>>) {
let mut ws = *websocket.lock().unwrap();
Error:
error[E0507]: cannot move out of dereference of `std::sync::MutexGuard<'_, Ws>`
--> src/ftx.rs:20:18
|
20 | let mut ws = *websocket.lock().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| move occurs because value has type `Ws`, which does not implement the `Copy` trait
| help: consider borrowing here: `&*websocket.lock().unwrap()`
My goal is to be able to pass websocket of type Ws to a function. The function will borrow WS mutable, call subscribe method on it, which mutates it, and return.
If you want to borrow mut &mut T, you can use Mutex::get_mut
Or lock+deref_mut over the MutexGuard
use std::sync::Arc;
use std::sync::Mutex;
fn main() {
let data = Arc::new(Mutex::new(0usize));
let mut inner = data.lock().unwrap();
*inner += 10;
println!("{}", inner);
}
Playground
Your real problem is that you are dereferencing while assigning it, so it is trying to move the value which invalidates the Arc<Mutex>. Do not use * as per the simple example above:
let mut ws = websocket.lock().unwrap();

What allows the implicit conversion from a struct to its reference when calling a method? [duplicate]

This question already has answers here:
What are Rust's exact auto-dereferencing rules?
(4 answers)
Closed 4 years ago.
Which rule makes the following code work?
struct Dummy(i32);
impl Dummy {
pub fn borrow(&self) {
println!("{}", self.0);
}
}
fn main() {
let d = Dummy(1);
(&d).borrow();
d.borrow();
}
I expect d.borrow() won't work as it passes in self which doesn't match the method signature borrow(&self).
From the reference :
A method call consists of an expression (the receiver) followed by a
single dot, an expression path segment, and a parenthesized
expression-list
When looking up a method call, the receiver may be automatically
dereferenced or borrowed in order to call a method.
Note:
Automatic dereference or borrow is only valid for the receiver. If there is no expression as receiver it will not work. Compiler will expect the borrowed type.
Example:
fn main() {
let d = Dummy(1);
let borrowed = Dummy::borrow(d);
}
Compiler will show an error:
error[E0308]: mismatched types
--> src/main.rs:12:34
|
12 | let borrowed = Dummy::borrow(d);
| ^
| |
| expected &Dummy, found struct `Dummy`
| help: consider borrowing here: `&d`
|
= note: expected type `&Dummy`
found type `Dummy`

Cannot print a process::Command because "borrowed value does not live long enough" [duplicate]

This question already has answers here:
"borrowed value does not live long enough" when using the builder pattern
(1 answer)
Builder pattern - borrowed value does not live long enough
(1 answer)
Closed 4 years ago.
I want a way to print the command with its arguments. In my real case, those arguments are generated and I want to see the command that we're going to run.
I'm trying to do this:
fn main() {
use std::process::Command;
let x = Command::new("sh").arg("2");
let y = x.output();
println!("status: {:#?}", x);
println!("status: {:#?}", y);
}
error[E0597]: borrowed value does not live long enough
--> src/main.rs:4:13
|
4 | let x = Command::new("sh").arg("2");
| ^^^^^^^^^^^^^^^^^^ - temporary value dropped here while still borrowed
| |
| temporary value does not live long enough
...
10 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime
I can get it to work if I don't add the .arg("2") above, but that doesn't help me with my usecase.
All the other examples on stackoverflow doesn't seem to help me solving this.
Command::arg takes self by mutable reference, so you need to store the Command returned by Command::new in a variable before calling arg, otherwise the Command would be dropped at the end of the statement. (The compiler could in theory use a hidden variable here as it does in other circumstances, but it doesn't do it as of Rust 1.29.)
fn main() {
use std::process::Command;
let mut x = Command::new("sh");
x.arg("2");
let y = x.output();
println!("status: {:#?}", x);
println!("status: {:#?}", y);
}

Conditionally converting the standard output of a Command to a string does not live long enough

I'm writing an application that needs to lookup the path of a binary using which. I already found out how to run a command, but I can't store the output.stdout to a variable that I can use.
use std::process::Command;
use std::str;
fn main() {
let interpreter: &str = "php72";
let binary: &str = "composer";
let mut _binary_path: &str = "";
if interpreter != "" {
let output = Command::new("which")
.arg(binary)
.output()
.expect("Execution of 'which' failed.");
_binary_path = str::from_utf8(&output.stdout).unwrap();
}
}
playground
This results in the following error:
error[E0597]: `output.stdout` does not live long enough
--> src/main.rs:14:40
|
14 | _binary_path = str::from_utf8(&output.stdout).unwrap();
| ^^^^^^^^^^^^^ borrowed value does not live long enough
15 | }
| - `output.stdout` dropped here while still borrowed
16 | }
| - borrowed value needs to live until here
Borrowing and referencing is still a bit confusing to me, even though I've read the docs. I understand that the lifetime of output is limited, since it lives in an if statement. I don't understand why it won't let me copy the value to the scope of the main() function.
What's going on? What's the best way to read the stdout?
binary_path is a &'static str because it is initialized to a string literal. The result of calling str::from_utf8 is a &str with a shorter lifetime than that. You cannot make the value live longer. This is a huge reason that Rust exists.
The simplest thing you can do is switch to a String:
let mut binary_path = String::new();
if interpreter.is_empty() {
// ...
binary_path = String::from_utf8(output.stdout).unwrap();
}
You could also use a Cow if you benchmarked that always allocating the binary_path is poor for performance.
See also:
Return local String as a slice (&str)
How do I convert a Vector of bytes (u8) to a string
Return either a borrowed or owned type in Rust
How to convert a String into a &'static str

How to increase lifetime of the bindings [duplicate]

This question already has answers here:
Extending borrowed lifetime for String slice
(2 answers)
Closed 5 years ago.
I have the following code ...
use std::process::Command;
fn main() {
let cmds = vec![vec!["ls", "-lh"], vec!["grep", "foo"]];
let mut processes: Vec<&mut Command> = Vec::new();
let mut i = 0;
let length = cmds.len();
while i < length {
let cmd = cmds[i].clone();
let mut p = Command::new(&cmd[0]).args(&(cmd[1..]));
processes.push(p);
i += 1;
}
println!("processes: {:?}", processes);
// want to manipulate processes elements here again.
// ...
}
Which doesn't compile:
error: borrowed value does not live long enough
--> src/main.rs:11:60
|
11 | let mut p = Command::new(&cmd[0]).args(&(cmd[1..]));
| --------------------- ^ temporary value dropped here while still borrowed
| |
| temporary value created here
...
19 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime
I understand why it refused to compile, I just don't know how to fix it in this case.
Instead of storing a borrowed reference, you could store the Command object itself.
let cmds = vec![vec!["ls", "-lh"], vec!["grep", "foo"]];
let mut processes: Vec<Command> = Vec::new();
// ^ you can store concrete objects instead of references.
for cmd in &cmds {
// ^ prefer a `for` loop over a `while` loop. (Also, you don't need to clone the cmds)
let mut p = Command::new(cmd[0]);
p.args(&cmd[1..]);
// ^ you can get a concrete `Command` instead of `&mut Command` reference
// if you store the returned object from `new()`.
processes.push(p);
}
println!("processes: {:?}", processes);
// processes: ["ls" "-lh", "grep" "foo"]

Resources