Cannot spawn onboard process

Following this example:

I'm trying to port it to rust. Even though seemingly I use the same api I cannot spawn onboard process:
C call (from the example):

gboolean retval;
  gchar *cmd = g_strdup("onboard -e -l Phone -t ModelM -s 400x300");
  gchar **arg_v = NULL;
  gint std_out = 0;
  GError *error = NULL;
  GIOChannel *std_out_ch;

  g_shell_parse_argv(cmd, NULL, &arg_v, NULL);
  gchar *_a = arg_v[1];
  retval = g_spawn_async_with_pipes(NULL, arg_v, NULL,
                                    static_cast<GSpawnFlags>(G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH), NULL,
                                    NULL, &child_pid, NULL, &std_out, NULL, &error);

My attempt in rust:

 let working_directory = "/";
    let argv: [&Path; 8] = [
        Path::new("onboard"),
        Path::new("-e"),
        Path::new("-l"),
        Path::new("Phone"),
        Path::new("-t"),
        Path::new("ModelM"),
        Path::new("-s"),
        Path::new("400x300"),
    ];
    let envp: [&Path; 1] = [Path::new("")];
    let flags = glib::SpawnFlags::DO_NOT_REAP_CHILD | glib::SpawnFlags::SEARCH_PATH;
    let child_setup = None;
    let io: Result<(Pid, i32, i32, i32), Error> =
        glib::spawn_async_with_pipes(working_directory, &argv, &envp, flags, child_setup);

Even though I'm getting OK in the result I don't see on my toolbar that the indicator of onboard being spawned.
I'm not sure if I pass all the params correctly, for example, in C the first param is NULL, I don't think I can do it with rust in that specific call.
Any help greatly appreciated.
Thank you.

For an exact equivalent of the C++ code, you'd want to do something like this:

use glib::{error::Error, Pid, SpawnFlags};
use std::{env, path::Path};
let working_directory = env::current_dir().unwrap();
let argv = [
    Path::new("onboard"),
    Path::new("-e"),
    Path::new("-l"),
    Path::new("Phone"),
    Path::new("-t"),
    Path::new("ModelM"),
    Path::new("-s"),
    Path::new("400x300"),
];
let environ = glib::environ();
let envp: Vec<&Path> = environ
    .iter()
    .map(Path::new)
    .collect();
let flags = SpawnFlags::DO_NOT_REAP_CHILD | SpawnFlags::SEARCH_PATH;
let child_setup = None;
let io: Result<(Pid, i32, i32, i32), Error> =
    glib::spawn_async_with_pipes(working_directory, &argv, &envp, flags, child_setup);

Does this fix the issue?

1 Like

Hi, yes that solved the issue. Thank you very much. If I may ask you one question with regards to the OP. The envp variable, that seems to be the main culprit. What was your train of thoughts that you've figured out that this causes the issue of not spawning the process?
Once again, thank you for your help.

I noticed that the example C++ code uses NULL for both the current directory and for the environment variable, which, according to GLib's documentation, makes them inherit the values from the current process. Most programs requires at least some environment variables to make sense of their environment; think about important things like $PATH or $HOME. So it seemed odd to me that you were passing an empty set environment variables to the child process. (It really seems like a shortcoming of the glib bindings that you need to manually compute arguments that GLib can compute for you.)

1 Like

Thanks, that was really helpful explanation.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.