src/tools/daemon.rs: reopen STDOUT/STDERR journald streams to get correct PID in logs
This commit is contained in:
		@ -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();
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user