Skip to content

Commit b1f7105

Browse files
committed
Make client-socket into a feature
So we can use it on F37+ builds.
1 parent d8997f3 commit b1f7105

File tree

5 files changed

+52
-33
lines changed

5 files changed

+52
-33
lines changed

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ lto = "thin"
123123
# Note: If you add a feature here, you also probably want to update utils.rs:get_features()
124124
fedora-integration = []
125125
rhsm = ["libdnf-sys/rhsm"]
126+
# Enable hard requirement on `rpm-ostreed.socket`; requires https://bugzilla.redhat.com/show_bug.cgi?id=2110012
127+
client-socket = []
126128
bin-unit-tests = []
127129
# ASAN+UBSAN
128130
sanitizers = []

rust/src/client.rs

+35-1
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,26 @@ pub(crate) fn client_handle_fd_argument(
154154
}
155155
}
156156

157+
/// Connect to the client socket and ensure the daemon is initialized;
158+
/// this avoids DBus and ensures that we get any early startup errors
159+
/// returned cleanly.
160+
#[cfg(feature = "client-socket")]
161+
fn start_daemon_via_socket() -> Result<()> {
162+
let address = "/run/rpm-ostree/client.sock";
163+
tracing::debug!("Starting daemon via {address}");
164+
let s = std::os::unix::net::UnixStream::connect(address)
165+
.with_context(|| anyhow!("Failed to connect to {}", address))?;
166+
let mut s = std::io::BufReader::new(s);
167+
let mut r = String::new();
168+
s.read_to_string(&mut r)
169+
.context("Reading from client socket")?;
170+
if r.is_empty() {
171+
Ok(())
172+
} else {
173+
Err(anyhow!("{r}").into())
174+
}
175+
}
176+
157177
/// Explicitly ensure the daemon is started via systemd, if possible.
158178
///
159179
/// This works around bugs from DBus activation, see
@@ -164,12 +184,14 @@ pub(crate) fn client_handle_fd_argument(
164184
/// to systemd directly and use its client tools to scrape errors.
165185
///
166186
/// What we really should do probably is use native socket activation.
167-
pub(crate) fn client_start_daemon() -> CxxResult<()> {
187+
#[cfg(not(feature = "client-socket"))]
188+
fn start_daemon_via_systemctl() -> Result<()> {
168189
let service = "rpm-ostreed.service";
169190
// Assume non-root can't use systemd right now.
170191
if rustix::process::getuid().as_raw() != 0 {
171192
return Ok(());
172193
}
194+
173195
// Unfortunately, RHEL8 systemd will count "systemctl start"
174196
// invocations against the restart limit, so query the status
175197
// first.
@@ -196,6 +218,18 @@ pub(crate) fn client_start_daemon() -> CxxResult<()> {
196218
Ok(())
197219
}
198220

221+
pub(crate) fn client_start_daemon() -> CxxResult<()> {
222+
// systemctl and socket paths only work for root right now; in the future
223+
// the socket may be opened up.
224+
if rustix::process::getuid().as_raw() != 0 {
225+
return Ok(());
226+
}
227+
#[cfg(feature = "client-socket")]
228+
return start_daemon_via_socket().map_err(Into::into);
229+
#[cfg(not(feature = "client-socket"))]
230+
return start_daemon_via_systemctl().map_err(Into::into);
231+
}
232+
199233
/// Convert the GVariant parameters from the DownloadProgress DBus API to a human-readable English string.
200234
pub(crate) fn client_render_download_progress(progress: &crate::ffi::GVariant) -> String {
201235
let progress = progress

rust/src/daemon.rs

+15-29
Original file line numberDiff line numberDiff line change
@@ -135,25 +135,6 @@ fn deployment_populate_variant_origin(
135135
Ok(())
136136
}
137137

138-
/// Connect to the client socket and ensure the daemon is initialized;
139-
/// this avoids DBus and ensures that we get any early startup errors
140-
/// returned cleanly.
141-
pub(crate) fn start_daemon_via_socket() -> CxxResult<()> {
142-
let address = "/run/rpm-ostree/client.sock";
143-
tracing::debug!("Starting daemon via {address}");
144-
let s = std::os::unix::net::UnixStream::connect(address)
145-
.with_context(|| anyhow!("Failed to connect to {}", address))?;
146-
let mut s = std::io::BufReader::new(s);
147-
let mut r = String::new();
148-
s.read_to_string(&mut r)
149-
.context("Reading from client socket")?;
150-
if r.is_empty() {
151-
Ok(())
152-
} else {
153-
Err(anyhow!("{r}").into())
154-
}
155-
}
156-
157138
async fn send_ok_result_to_client(_client: UnixStream) {
158139
// On success we close the stream without writing anything,
159140
// which acknowledges successful startup to the client.
@@ -229,7 +210,10 @@ pub(crate) fn daemon_main(debug: bool) -> Result<()> {
229210
// directly propagate the error back to our exit code.
230211
init_res?;
231212
tracing::debug!("Initializing directly (not socket activated)");
232-
StdUnixListener::bind("/run/rpm-ostree/client.sock")?
213+
cfg!(feature = "client-socket")
214+
.then(|| StdUnixListener::bind("/run/rpm-ostree/client.sock"))
215+
.transpose()
216+
.context("Binding to socket")?
233217
}
234218
Some(fd) => {
235219
if fds.next().is_some() {
@@ -239,7 +223,7 @@ pub(crate) fn daemon_main(debug: bool) -> Result<()> {
239223
let listener = unsafe { StdUnixListener::from_raw_fd(fd) };
240224

241225
match init_res {
242-
Ok(_) => listener,
226+
Ok(_) => Some(listener),
243227
Err(e) => {
244228
let err_copy = anyhow!("{e}");
245229
tracing::debug!("Reporting initialization error: {e}");
@@ -257,16 +241,18 @@ pub(crate) fn daemon_main(debug: bool) -> Result<()> {
257241
}
258242
};
259243

260-
let (shutdown_send, shutdown_recv) = tokio::sync::oneshot::channel();
261-
(*SHUTDOWN_SIGNAL).lock().unwrap().replace(shutdown_send);
244+
if let Some(listener) = listener {
245+
let (shutdown_send, shutdown_recv) = tokio::sync::oneshot::channel();
246+
(*SHUTDOWN_SIGNAL).lock().unwrap().replace(shutdown_send);
262247

263-
let listener = UnixListener::from_std(listener)?;
248+
let listener = UnixListener::from_std(listener)?;
264249

265-
// On success, we spawn a helper task that just responds with
266-
// sucess to clients that connect via the socket. In the future,
267-
// perhaps we'll expose an API here.
268-
tracing::debug!("Spawning acknowledgement task");
269-
tokio::task::spawn(async { process_clients_with_ok(listener, shutdown_recv).await });
250+
// On success, we spawn a helper task that just responds with
251+
// sucess to clients that connect via the socket. In the future,
252+
// perhaps we'll expose an API here.
253+
tracing::debug!("Spawning acknowledgement task");
254+
tokio::task::spawn(async { process_clients_with_ok(listener, shutdown_recv).await });
255+
}
270256

271257
tracing::debug!("Entering daemon mainloop");
272258
// And now, enter the main loop.

rust/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ pub mod ffi {
300300
// daemon.rs
301301
extern "Rust" {
302302
fn daemon_main(debug: bool) -> Result<()>;
303-
fn start_daemon_via_socket() -> Result<()>;
304303
fn daemon_terminate();
305304
fn daemon_sanitycheck_environment(sysroot: &OstreeSysroot) -> Result<()>;
306305
fn deployment_generate_id(deployment: &OstreeDeployment) -> String;

src/app/libmain.cxx

-2
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,6 @@ rpmostree_option_context_parse (GOptionContext *context, const GOptionEntry *mai
281281
return rpmostreecxx::client_throw_non_ostree_host_error (error);
282282
}
283283

284-
CXX_TRY (rpmostreecxx::start_daemon_via_socket (), error);
285-
286284
/* root never needs to auth */
287285
if (getuid () != 0)
288286
/* ignore errors; we print out a warning if we fail to spawn pkttyagent */

0 commit comments

Comments
 (0)