dbus or libdbus appears to close the connection when stdin from a console (/dev/tty*) is sent as an argument
I bumped into an interesting issue where sending stdin from a process with a pseudoterminal as the controlling terminal works properly, but when run from a console, the following error is encountered: https://github.com/stratis-storage/project/issues/233.
The specific error of note here is org.freedesktop.DBus.Error.Disconnected
. We have an alternate IPC mechanism that uses Unix sockets to transfer the file descriptor so I tried sending stdin from the console to the daemon process and that worked. This rules out that this is a limitation of Unix sockets. I also wondered if this had to do with the Python libraries that we use on top of python-dbus in our Python CLI. I wanted to rule that out so I wrote a D-Bus client in Rust to invoke just the problematic D-Bus method call:
use std::{error::Error, io::stdin, os::unix::io::AsRawFd, time::Duration};
use dbus::{arg::OwnedFd, blocking::Connection};
fn main() -> Result<(), Box<dyn Error>> {
let key_desc = std::env::args()
.nth(1)
.ok_or_else(|| "Key description is a required argument")?;
let connection = Connection::new_system()?;
let proxy = connection.with_proxy(
"org.storage.stratis2",
"/org/storage/stratis2",
Duration::from_secs(5),
);
println!("Enter key data:");
let ((changed, _), rc, rs): ((bool, bool), u16, String) = proxy.method_call(
"org.storage.stratis2.Manager.r2",
"SetKey",
(key_desc, unsafe { OwnedFd::new(stdin().as_raw_fd()) }, true),
)?;
if rc != 0 {
Err(format!("Failed with error code {}: {}", rc, rs))?
} else if !changed {
Err("The requested action had no effect")?
} else {
Ok(())
}
}
This also worked from a pseudoterminal-controlled shell, and failed with the same error when run from the console. This leads me to believe that this is a bug in either dbus itself or libdbus as both the Rust library (dbus-rs) and python-dbus bind to libdbus.
One additional piece of information that might be useful is that I monitored the D-Bus while this was occuring and no call to our SetKey
method is ever registered in dbus-monitor
indicating that it is never actually sent across the D-Bus before the connection is closed. strace also seems to indicate that the sendmsg
call that is supposed to send the SetKey
message succeeds according to the return value, but immediately after that, the recvmsg
call appears to get a SIGHUP
and returns 0 bytes read. The file descriptor for the D-Bus connection is then closed.
Let me know if you need any more information.