Gio - output differs for terminal (CLI) and execv() in C(++)

In regard to GLib/gio - g_volume_get_connected_drives returns NULL

On my Ubuntu 22.04, when running the command

/usr/bin/gio mount -l

I receive such similar output:

Drive(0): *HARDDRIVE*
  Type: GProxyDrive (GProxyVolumeMonitorUDisks2)
Volume(0): *WEBDAVMOUNT*
  Type: GProxyVolume (GProxyVolumeMonitorUDisks2)

However, if I create and run the following program in C/C++

int main(int argc, char* argv[]){
    char* const GIO_ARGUMENTS[] = {"/usr/bin/gio", "mount", "--list", NULL};

    pid_t child_process;

    child_process = fork();

    int child_return_status = 0;

    if(child_process == -1){
        std::cout << "Error forking" << std::endl;

        exit(EXIT_FAILURE);
    }
    else if(child_process == 0){
        execv(GIO_ARGUMENTS[0], GIO_ARGUMENTS);
        std::cout << "Child exiting" << std::endl;
        exit(EXIT_SUCCESS);
    }
    else{
        std::cout << "In parent waiting for child" << std::endl;
        waitpid(WAIT_ANY, &child_return_status, WUNTRACED);

        std::cout << "Parent exiting" << std::endl;

        exit(EXIT_SUCCESS);
    }
}

I only receive this output (notice the Drive(0) part is missing):

Volume(0): *WEBDAVMOUNT*
  Type: GProxyVolume (GProxyVolumeMonitorUDisks2)

Both the command line call and the executable run under my user, so there is no difference in context. Even if I attach another device (smartphone with file sharing option enabled) it does not show up. What is the cause for this and how to make gio display exactly as in the CLI?

The discrepancy you’re seeing between running /usr/bin/gio mount -l directly in the terminal and running it from your C/C++ program comes down to environment differences, even though both run under the same user.

Specifically, GIO and GVfs (GIO’s virtual filesystem layer) rely on certain environment variables and session services (like D-Bus and GVfs daemons) that are typically initialized when you run a full graphical login session. These include:

  • A valid DBUS_SESSION_BUS_ADDRESS
  • Running gvfsd, gvfs-udisks2-volume-monitor, and related daemons
  • Environment variables like XDG_RUNTIME_DIR

Why your C++ program doesn’t show drives

When you launch a process via execv() in a minimal environment (like your C/C++ program), you’re not inheriting all the session environment variables, especially those that GIO depends on to interface with system and user volumes.

As a result, the subprocess may only be able to see GIO volumes that do not require full session context (like WebDAV mounts), while missing those that need deeper integration (e.g., physical drives).

This is why you’re seeing Drive(0) missing — the GIO volume monitor backend for drives is not functioning fully in that environment.

How to fix it

To make your C++ program behave exactly like the shell does, you need to replicate the environment. Here are your options:

1. Pass the full environment using execve() or execle() instead of execv()

extern char **environ;
execve(GIO_ARGUMENTS[0], GIO_ARGUMENTS, environ);

This ensures the new process inherits the same environment as your parent (including DBUS_SESSION_BUS_ADDRESS, which is critical).

2. Make sure the D-Bus session address is present

You can check this in your environment with:

echo $DBUS_SESSION_BUS_ADDRESS

If your program is missing this, you can manually fetch and set it (though it’s better to inherit the environment). To get the value dynamically:

export DBUS_SESSION_BUS_ADDRESS=$(cat /run/user/$(id -u)/bus)

Or in C/C++, setenv before calling execv():

setenv("DBUS_SESSION_BUS_ADDRESS", "...", 1);

3. Use GIO_USE_VFS=local or unset it if it’s interfering

This env var can sometimes interfere with what backends GIO uses. Try explicitly unsetting it:

unsetenv("GIO_USE_VFS");

Or at least ensure it’s not overriding anything.

4. Call gio mount -l directly in a shell using system() for debugging

Try temporarily replacing your execv() call with:

system("/usr/bin/gio mount -l");

If this version shows Drive(0), it’s a clear confirmation that the missing environment is the cause.

5. Consider using GLib APIs directly

If you’re trying to integrate with GIO programmatically, you might be better off using GLib’s GIO API (e.g., g_volume_monitor_get(), g_volume_get_drive()), but the same environment concerns apply.

Summary

You’re missing key environment variables (most likely DBUS_SESSION_BUS_ADDRESS and related GIO session setup) in your execv()-launched process. Use execve() with inherited environ or carefully set the needed variables manually. This will align the runtime environment with what your interactive shell provides, allowing GIO to detect and show all drives.