Skip to content

Commit c2e2737

Browse files
swsnrhawkw
authored andcommitted
journald: use unconnected socket (#1758)
Lets journald subscribers survive a journald restart. Closes #1745 ## Motivation Currently the journald subscriber immediately connects to the journald socket. As such I understand it'd not survive a full restart of journald. ## Solution Do not connect the client socket immediately; instead pass the socket pathname every time we send a message. This is also what upstream does.
1 parent 1c3d703 commit c2e2737

File tree

2 files changed

+44
-14
lines changed

2 files changed

+44
-14
lines changed

tracing-journald/src/lib.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ pub struct Layer {
8686
field_prefix: Option<String>,
8787
}
8888

89+
#[cfg(unix)]
90+
const JOURNALD_PATH: &str = "/run/systemd/journal/socket";
91+
8992
impl Layer {
9093
/// Construct a journald layer
9194
///
@@ -95,11 +98,14 @@ impl Layer {
9598
#[cfg(unix)]
9699
{
97100
let socket = UnixDatagram::unbound()?;
98-
socket.connect("/run/systemd/journal/socket")?;
99-
Ok(Self {
101+
let layer = Self {
100102
socket,
101103
field_prefix: Some("F".into()),
102-
})
104+
};
105+
// Check that we can talk to journald, by sending empty payload which journald discards.
106+
// However if the socket didn't exist or if none listened we'd get an error here.
107+
layer.send_payload(&[])?;
108+
Ok(layer)
103109
}
104110
#[cfg(not(unix))]
105111
Err(io::Error::new(
@@ -125,13 +131,15 @@ impl Layer {
125131

126132
#[cfg(unix)]
127133
fn send_payload(&self, payload: &[u8]) -> io::Result<usize> {
128-
self.socket.send(payload).or_else(|error| {
129-
if Some(libc::EMSGSIZE) == error.raw_os_error() {
130-
self.send_large_payload(payload)
131-
} else {
132-
Err(error)
133-
}
134-
})
134+
self.socket
135+
.send_to(payload, JOURNALD_PATH)
136+
.or_else(|error| {
137+
if Some(libc::EMSGSIZE) == error.raw_os_error() {
138+
self.send_large_payload(payload)
139+
} else {
140+
Err(error)
141+
}
142+
})
135143
}
136144

137145
#[cfg(all(unix, not(target_os = "linux")))]
@@ -154,7 +162,7 @@ impl Layer {
154162
// Fully seal the memfd to signal journald that its backing data won't resize anymore
155163
// and so is safe to mmap.
156164
memfd::seal_fully(mem.as_raw_fd())?;
157-
socket::send_one_fd(&self.socket, mem.as_raw_fd())
165+
socket::send_one_fd_to(&self.socket, mem.as_raw_fd(), JOURNALD_PATH)
158166
}
159167
}
160168

tracing-journald/src/socket.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
33
use std::io::{Error, Result};
44
use std::mem::{size_of, zeroed};
5+
use std::os::unix::ffi::OsStrExt;
56
use std::os::unix::net::UnixDatagram;
67
use std::os::unix::prelude::{AsRawFd, RawFd};
8+
use std::path::Path;
79
use std::ptr;
810

911
use libc::*;
@@ -31,18 +33,38 @@ fn cmsg_buffer_size_for_one_fd() {
3133
assert_cmsg_bufsize()
3234
}
3335

34-
pub fn send_one_fd(socket: &UnixDatagram, fd: RawFd) -> Result<usize> {
36+
pub fn send_one_fd_to<P: AsRef<Path>>(socket: &UnixDatagram, fd: RawFd, path: P) -> Result<usize> {
3537
assert_cmsg_bufsize();
3638

37-
let mut cmsg_buffer = AlignedBuffer {
38-
buffer: ([0u8; CMSG_BUFSIZE]),
39+
let mut addr: sockaddr_un = unsafe { zeroed() };
40+
let path_bytes = path.as_ref().as_os_str().as_bytes();
41+
// path_bytes may have at most sun_path + 1 bytes, to account for the trailing NUL byte.
42+
if addr.sun_path.len() <= path_bytes.len() {
43+
return Err(Error::from_raw_os_error(ENAMETOOLONG));
44+
}
45+
46+
addr.sun_family = AF_UNIX as _;
47+
unsafe {
48+
std::ptr::copy_nonoverlapping(
49+
path_bytes.as_ptr(),
50+
addr.sun_path.as_mut_ptr() as *mut u8,
51+
path_bytes.len(),
52+
)
3953
};
54+
4055
let mut msg: msghdr = unsafe { zeroed() };
56+
// Set the target address.
57+
msg.msg_name = &mut addr as *mut _ as *mut c_void;
58+
msg.msg_namelen = size_of::<sockaddr_un>() as socklen_t;
4159

4260
// We send no data body with this message.
4361
msg.msg_iov = ptr::null_mut();
4462
msg.msg_iovlen = 0;
4563

64+
// Create and fill the control message buffer with our file descriptor
65+
let mut cmsg_buffer = AlignedBuffer {
66+
buffer: ([0u8; CMSG_BUFSIZE]),
67+
};
4668
msg.msg_control = unsafe { cmsg_buffer.buffer.as_mut_ptr() as _ };
4769
msg.msg_controllen = unsafe { CMSG_SPACE(size_of::<RawFd>() as _) as _ };
4870

0 commit comments

Comments
 (0)