src/tools/daemon.rs: reopen STDOUT/STDERR journald streams to get correct PID in logs

This commit is contained in:
Dietmar Maurer 2020-06-22 13:06:11 +02:00
parent 00c2327564
commit 3ddb14889a

View File

@ -3,12 +3,13 @@
use std::ffi::CString; use std::ffi::CString;
use std::future::Future; use std::future::Future;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_uchar, c_int};
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::unix::ffi::OsStrExt; use std::os::unix::ffi::OsStrExt;
use std::panic::UnwindSafe; use std::panic::UnwindSafe;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::path::PathBuf;
use anyhow::{bail, format_err, Error}; use anyhow::{bail, format_err, Error};
@ -17,6 +18,11 @@ use proxmox::tools::io::{ReadExt, WriteExt};
use crate::server; use crate::server;
use crate::tools::{fd_change_cloexec, self}; use crate::tools::{fd_change_cloexec, self};
#[link(name = "systemd")]
extern "C" {
fn sd_journal_stream_fd(identifier: *const c_uchar, priority: c_int, level_prefix: c_int) -> c_int;
}
// Unfortunately FnBox is nightly-only and Box<FnOnce> is unusable, so just use Box<Fn>... // Unfortunately FnBox is nightly-only and Box<FnOnce> is unusable, so just use Box<Fn>...
pub type BoxedStoreFunc = Box<dyn FnMut() -> Result<String, Error> + UnwindSafe + Send>; pub type BoxedStoreFunc = Box<dyn FnMut() -> Result<String, Error> + UnwindSafe + Send>;
@ -32,7 +38,7 @@ pub trait Reloadable: Sized {
#[derive(Default)] #[derive(Default)]
pub struct Reloader { pub struct Reloader {
pre_exec: Vec<PreExecEntry>, pre_exec: Vec<PreExecEntry>,
self_exe: CString, self_exe: PathBuf,
} }
// Currently we only need environment variables for storage, but in theory we could also add // Currently we only need environment variables for storage, but in theory we could also add
@ -47,12 +53,8 @@ impl Reloader {
Ok(Self { Ok(Self {
pre_exec: Vec::new(), pre_exec: Vec::new(),
// Get the path to our executable as CString // Get the path to our executable as PathBuf
self_exe: CString::new( self_exe: std::fs::read_link("/proc/self/exe")?,
std::fs::read_link("/proc/self/exe")?
.into_os_string()
.as_bytes()
)?
}) })
} }
@ -129,6 +131,25 @@ impl Reloader {
assert_eq!(ok[0], 1, "reload handshake should have sent a 1 byte"); assert_eq!(ok[0], 1, "reload handshake should have sent a 1 byte");
std::mem::drop(pnew); std::mem::drop(pnew);
// Try to reopen STDOUT/STDERR journald streams to get correct PID in logs
let ident = CString::new(self.self_exe.file_name().unwrap().as_bytes()).unwrap();
let ident = ident.as_bytes();
let fd = unsafe { sd_journal_stream_fd(ident.as_ptr(), libc::LOG_INFO, 1) };
if fd >= 0 && fd != 1 {
let fd = proxmox::tools::fd::Fd(fd); // add drop handler
nix::unistd::dup2(fd.as_raw_fd(), 1)?;
} else {
log::error!("failed to update STDOUT journal redirection ({})", fd);
}
let fd = unsafe { sd_journal_stream_fd(ident.as_ptr(), libc::LOG_ERR, 1) };
if fd >= 0 && fd != 2 {
let fd = proxmox::tools::fd::Fd(fd); // add drop handler
nix::unistd::dup2(fd.as_raw_fd(), 2)?;
} else {
log::error!("failed to update STDERR journal redirection ({})", fd);
}
self.do_reexec(new_args) self.do_reexec(new_args)
}) })
{ {
@ -182,7 +203,7 @@ impl Reloader {
} }
fn do_reexec(self, args: Vec<CString>) -> Result<(), Error> { fn do_reexec(self, args: Vec<CString>) -> Result<(), Error> {
let exe = self.self_exe.clone(); let exe = CString::new(self.self_exe.as_os_str().as_bytes())?;
self.pre_exec()?; self.pre_exec()?;
nix::unistd::setsid()?; nix::unistd::setsid()?;
let args: Vec<&std::ffi::CStr> = args.iter().map(|s| s.as_ref()).collect(); let args: Vec<&std::ffi::CStr> = args.iter().map(|s| s.as_ref()).collect();