Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

71%
+3 −0
Q&A How to correctly daemonize a Rocket-based app?

Summary I'm refactoring a Rust-based service/daemon to move away from gRPC and use a Rocket-based API instead. I'm also using the daemonize crate to turn the foreground process into a background p...

1 answer  ·  posted 2y ago by ghost-in-the-zsh‭  ·  last activity 2y ago by ghost-in-the-zsh‭

Question rust rocket daemon
#4: Post edited by user avatar ghost-in-the-zsh‭ · 2022-07-11T18:03:40Z (over 2 years ago)
Add first update with Wireshark packet capture image
  • # Summary
  • I'm refactoring a Rust-based service/daemon to move away from gRPC and use a [Rocket](https://rocket.rs)-based API instead. I'm also using the [`daemonize`](https://crates.io/crates/daemonize) crate to turn the foreground process into a background process.
  • The problem I've run into is that when I get the `rocket`-based service to successfully daemonize itself (i.e. `daemon.start()` returns `Ok()` result), it *never* receives the HTTP requests sent to it. In other words, no HTTP requests are ever logged as having been received by Rocket while the client side (i.e. `curl -X GET ...` in this case) keeps waiting for a response until it times out.
  • If I run the Rocket-based service in the foreground, i.e. without `daemonize`, then it works as expected. Also, my usage of `daemonize` before refactoring the service to use Rocket was showing correct behavior.
  • # Questions
  • Given the constraints (see later):
  • 1. How can I get Rocket to work properly when turned into a background process with daemonize?
  • 2. Is there a better approach than using daemonize to turn a Rocket app into a background service?
  • 3. Any suggestions on gathering more data to troubleshoot this issue (e.g. determine if Rocket is failing to receive requests or refusing to process them - i.e. hung)? (I'll be running a few tests later with `tcpdump` to see what I can find out.)
  • The only thing that stands out here is my attempt to mix Rocket with Daemonize. The Rocket docs don't seem to have info on how to turn run it as a background service.
  • ### Constraints
  • 1. Launching the service as `./service &` will not be possible in production;
  • 2. This is on an embedded device running Yocto and `systemd` is *not* available, so I cannot replace my usage of `daemonize` by a service unit
  • Please note that the above are not my decisions to make, are beyond my control, and are not likely to change. (I'm still looking into it, but, for the sake of this question, we should *assume* that it won't be possible.)
  • # Code Ref
  • Here's the code using `daemonize` for reference:
  • ```rust
  • fn launch_background(figment: Figment, config: Config) -> Rocket<Build> {
  • let daemon = Daemonize::new()
  • .pid_file(config.service.files.pid_file.clone())
  • .chown_pid_file(true)
  • .working_directory(config.service.context.working_dir.clone())
  • .user(config.service.context.user.as_str())
  • .group(config.service.context.group.as_str())
  • .umask(config.service.context.umask)
  • .stderr(File::create(config.service.files.log_file.clone()).unwrap());
  • match daemon.start() {
  • Ok(_) => launch_foreground(figment, config),
  • Err(e) => ...
  • }
  • }
  • ```
  • Here's the code of how Rocket is being launched
  • ```rust
  • fn launch_foreground(figment: Figment, config: Config) -> Rocket<Build> {
  • rocket::custom(figment)
  • .manage(...)
  • .manage(...)
  • .mount(...)
  • .mount(...)
  • }
  • ```
  • This is what Rocket shows when launched, regardless of whether it's daemonized or not (shortened for brevity):
  • ```bash
  • [2022-07-09T00:46:00Z INFO rocket::launch] 🔧 Configured for default.
  • [2022-07-09T00:46:00Z INFO rocket::launch_] address: 127.0.0.1
  • [2022-07-09T00:46:00Z INFO rocket::launch_] port: 50051
  • <snip>
  • [2022-07-09T00:46:00Z INFO rocket::launch] 📬 Routes:
  • [2022-07-09T00:46:00Z INFO rocket::launch_] (get_config) GET ...
  • [2022-07-09T00:46:00Z INFO rocket::launch_] (get_downcast_info) GET ...
  • [2022-07-09T00:46:00Z INFO rocket::launch_] (get_downcast_state) GET ...
  • <snip>
  • [2022-07-09T00:46:00Z INFO rocket::launch] 🚀 Rocket has launched from http://127.0.0.1:50051
  • ```
  • From the above, there're no obvious issues. There're no warnings or errors either. However, when sending HTTP requests to the mounted endpoints, nothing is ever logged by Rocket, so it's either *not receiving* any requests or it's hung in some way and it's *not processing* anything. I think the latter is more likely, but I'm not sure why that would happen either.
  • # Summary
  • I'm refactoring a Rust-based service/daemon to move away from gRPC and use a [Rocket](https://rocket.rs)-based API instead. I'm also using the [`daemonize`](https://crates.io/crates/daemonize) crate to turn the foreground process into a background process.
  • The problem I've run into is that when I get the `rocket`-based service to successfully daemonize itself (i.e. `daemon.start()` returns `Ok()` result), it *never* receives the HTTP requests sent to it. In other words, no HTTP requests are ever logged as having been received by Rocket while the client side (i.e. `curl -X GET ...` in this case) keeps waiting for a response until it times out.
  • If I run the Rocket-based service in the foreground, i.e. without `daemonize`, then it works as expected. Also, my usage of `daemonize` before refactoring the service to use Rocket was showing correct behavior.
  • # Questions
  • Given the constraints (see later):
  • 1. How can I get Rocket to work properly when turned into a background process with daemonize?
  • 2. Is there a better approach than using daemonize to turn a Rocket app into a background service?
  • 3. Any suggestions on gathering more data to troubleshoot this issue (e.g. determine if Rocket is failing to receive requests or refusing to process them - i.e. hung)? (I'll be running a few tests later with `tcpdump` to see what I can find out.)
  • The only thing that stands out here is my attempt to mix Rocket with Daemonize. The Rocket docs don't seem to have info on how to turn run it as a background service.
  • ### Constraints
  • 1. Launching the service as `./service &` will not be possible in production;
  • 2. This is on an embedded device running Yocto and `systemd` is *not* available, so I cannot replace my usage of `daemonize` by a service unit
  • Please note that the above are not my decisions to make, are beyond my control, and are not likely to change. (I'm still looking into it, but, for the sake of this question, we should *assume* that it won't be possible.)
  • # Code Ref
  • Here's the code using `daemonize` for reference:
  • ```rust
  • fn launch_background(figment: Figment, config: Config) -> Rocket<Build> {
  • let daemon = Daemonize::new()
  • .pid_file(config.service.files.pid_file.clone())
  • .chown_pid_file(true)
  • .working_directory(config.service.context.working_dir.clone())
  • .user(config.service.context.user.as_str())
  • .group(config.service.context.group.as_str())
  • .umask(config.service.context.umask)
  • .stderr(File::create(config.service.files.log_file.clone()).unwrap());
  • match daemon.start() {
  • Ok(_) => launch_foreground(figment, config),
  • Err(e) => ...
  • }
  • }
  • ```
  • Here's the code of how Rocket is being launched
  • ```rust
  • fn launch_foreground(figment: Figment, config: Config) -> Rocket<Build> {
  • rocket::custom(figment)
  • .manage(...)
  • .manage(...)
  • .mount(...)
  • .mount(...)
  • }
  • ```
  • This is what Rocket shows when launched, regardless of whether it's daemonized or not (shortened for brevity):
  • ```bash
  • [2022-07-09T00:46:00Z INFO rocket::launch] 🔧 Configured for default.
  • [2022-07-09T00:46:00Z INFO rocket::launch_] address: 127.0.0.1
  • [2022-07-09T00:46:00Z INFO rocket::launch_] port: 50051
  • <snip>
  • [2022-07-09T00:46:00Z INFO rocket::launch] 📬 Routes:
  • [2022-07-09T00:46:00Z INFO rocket::launch_] (get_config) GET ...
  • [2022-07-09T00:46:00Z INFO rocket::launch_] (get_downcast_info) GET ...
  • [2022-07-09T00:46:00Z INFO rocket::launch_] (get_downcast_state) GET ...
  • <snip>
  • [2022-07-09T00:46:00Z INFO rocket::launch] 🚀 Rocket has launched from http://127.0.0.1:50051
  • ```
  • From the above, there're no obvious issues. There're no warnings or errors either. However, when sending HTTP requests to the mounted endpoints, nothing is ever logged by Rocket, so it's either *not receiving* any requests or it's hung in some way and it's *not processing* anything. I think the latter is more likely, but I'm not sure why that would happen either.
  • # Update
  • This is a packet capture using Wireshark when the Rocket app is running as a background service/daemon. Notice that the 5th packet (#153) is a transport layer TCP `ACK` packet from the Rocket app side following the client's application layer HTTP `GET` request packet (#152), but the app layer on the service end (i.e. Rocket itself) did not respond. After a while, Keep-Alive packets start to show up until the connection is, eventually, terminated.
  • ![Rocket/cURL Network Traffic](https://software.codidact.com/uploads/HUmwxjyQEdgdQU1oy73U2Qi1)
#3: Nominated for promotion by user avatar Alexei‭ · 2022-07-10T13:24:23Z (over 2 years ago)
#2: Post edited by user avatar ghost-in-the-zsh‭ · 2022-07-10T04:41:25Z (over 2 years ago)
Make title more accurate
  • Rocket fails to receive or process requests when Daemonized
  • How to correctly daemonize a Rocket-based app?
#1: Initial revision by user avatar ghost-in-the-zsh‭ · 2022-07-09T00:54:57Z (over 2 years ago)
Rocket fails to receive or process requests when Daemonized
# Summary

I'm refactoring a Rust-based service/daemon to move away from gRPC and use a [Rocket](https://rocket.rs)-based API instead. I'm also using the [`daemonize`](https://crates.io/crates/daemonize) crate to turn the foreground process into a background process.

The problem I've run into is that when I get the `rocket`-based service to successfully daemonize itself (i.e. `daemon.start()` returns `Ok()` result), it *never* receives the HTTP requests sent to it. In other words, no HTTP requests are ever logged as having been received by Rocket while the client side (i.e. `curl -X GET ...` in this case) keeps waiting for a response until it times out.

If I run the Rocket-based service in the foreground, i.e. without `daemonize`, then it works as expected. Also, my usage of `daemonize` before refactoring the service to use Rocket was showing correct behavior.

# Questions

Given the constraints (see later):

1. How can I get Rocket to work properly when turned into a background process with daemonize?
2. Is there a better approach than using daemonize to turn a Rocket app into a background service?
3. Any suggestions on gathering more data to troubleshoot this issue (e.g. determine if Rocket is failing to receive requests or refusing to process them - i.e. hung)? (I'll be running a few tests later with `tcpdump` to see what I can find out.)

The only thing that stands out here is my attempt to mix Rocket with Daemonize. The Rocket docs don't seem to have info on how to turn run it as a background service.

### Constraints

1. Launching the service as `./service &` will not be possible in production;
2. This is on an embedded device running Yocto and `systemd` is *not* available, so I cannot replace my usage of `daemonize` by a service unit

Please note that the above are not my decisions to make, are beyond my control, and are not likely to change. (I'm still looking into it, but, for the sake of this question, we should *assume* that it won't be possible.)

# Code Ref

Here's the code using `daemonize` for reference:

```rust
fn launch_background(figment: Figment, config: Config) -> Rocket<Build> {
    let daemon = Daemonize::new()
        .pid_file(config.service.files.pid_file.clone())
        .chown_pid_file(true)
        .working_directory(config.service.context.working_dir.clone())
        .user(config.service.context.user.as_str())
        .group(config.service.context.group.as_str())
        .umask(config.service.context.umask)
        .stderr(File::create(config.service.files.log_file.clone()).unwrap());

    match daemon.start() {
        Ok(_) => launch_foreground(figment, config),
        Err(e) => ...
    }
}
```

Here's the code of how Rocket is being launched

```rust
fn launch_foreground(figment: Figment, config: Config) -> Rocket<Build> {
    rocket::custom(figment)
        .manage(...)
        .manage(...)
        .mount(...)
        .mount(...)
}
```

This is what Rocket shows when launched, regardless of whether it's daemonized or not (shortened for brevity):

```bash
[2022-07-09T00:46:00Z INFO  rocket::launch] 🔧 Configured for default.
[2022-07-09T00:46:00Z INFO  rocket::launch_] address: 127.0.0.1
[2022-07-09T00:46:00Z INFO  rocket::launch_] port: 50051
<snip>
[2022-07-09T00:46:00Z INFO  rocket::launch] 📬 Routes:
[2022-07-09T00:46:00Z INFO  rocket::launch_] (get_config) GET ...
[2022-07-09T00:46:00Z INFO  rocket::launch_] (get_downcast_info) GET ...
[2022-07-09T00:46:00Z INFO  rocket::launch_] (get_downcast_state) GET ...
<snip>
[2022-07-09T00:46:00Z INFO  rocket::launch] 🚀 Rocket has launched from http://127.0.0.1:50051
```

From the above, there're no obvious issues. There're no warnings or errors either. However, when sending HTTP requests to the mounted endpoints, nothing is ever logged by Rocket, so it's either *not receiving* any requests or it's hung in some way and it's *not processing* anything. I think the latter is more likely, but I'm not sure why that would happen either.