mirror of
https://github.com/openai/codex.git
synced 2026-10-20 00:18:49 +00:00
Add a shared cleanup lock guard for local log directories (#55358)
## What changed Export `LocalLogsDir` from `codex-file-system` to create a caller-selected diagnostic directory and retain a shared directory lock on Unix. Clones share the lock so callers can keep it held until all log connections close. New directories use mode `0700` on Unix; existing permissions are preserved. Initialization checks that the locked directory still matches the selected path and returns an error if it changed. GitOrigin-RevId: fc870d7ee0997d67ba1a23f72ba4ac3cf89fd31a
This commit is contained in:
committed by
copyberry
parent
9b865ab31e
commit
18d09e1eda
@@ -1,6 +1,7 @@
|
||||
mod environment_accessor;
|
||||
mod exec_permission_profile_serde;
|
||||
mod find_up;
|
||||
mod local_logs;
|
||||
mod nfs;
|
||||
|
||||
use bytes::Bytes;
|
||||
@@ -30,6 +31,7 @@ pub use find_up::find_nearest_ancestor_with_markers;
|
||||
pub use find_up::find_nearest_native_ancestor_with_markers;
|
||||
use futures::Stream;
|
||||
use futures::stream::BoxStream;
|
||||
pub use local_logs::LocalLogsDir;
|
||||
pub use nfs::is_nfs;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
//! Creates the configured diagnostic directory and retains a shared directory lock on Unix.
|
||||
//! The caller selects the path. This module does not search for storage.
|
||||
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// A diagnostic directory with a Unix cleanup lock retained by all clones.
|
||||
#[derive(Clone, Debug)]
|
||||
#[must_use = "keep the guard until all log connections close"]
|
||||
pub struct LocalLogsDir {
|
||||
path: PathBuf,
|
||||
#[cfg(unix)]
|
||||
_cleanup_lock: std::sync::Arc<std::fs::File>,
|
||||
}
|
||||
|
||||
impl LocalLogsDir {
|
||||
/// Create the selected directory. Keep the guard until all log connections close.
|
||||
/// On Unix, newly created directories start with mode 0700. Existing permissions
|
||||
/// are preserved, including on user-created directories or after the user changes
|
||||
/// the mode. We do not enforce or restore private permissions on later calls.
|
||||
pub fn new(path: &Path) -> io::Result<Self> {
|
||||
let mut builder = std::fs::DirBuilder::new();
|
||||
builder.recursive(true);
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::DirBuilderExt;
|
||||
|
||||
// Set private permissions only at creation; preserve user-chosen modes afterward.
|
||||
builder.mode(0o700);
|
||||
}
|
||||
builder.create(path)?;
|
||||
// the main reason to use the diagnostic is to redirect the logs to the tmp/ or /dev/shm (tmpfs)
|
||||
// so on unix system we have to ensure that the directory is not going to be cleaned via shared lock
|
||||
#[cfg(unix)]
|
||||
let directory = {
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
let directory = std::fs::File::open(path)?;
|
||||
directory.try_lock_shared()?;
|
||||
let locked = directory.metadata()?;
|
||||
let current = std::fs::metadata(path)?;
|
||||
if !locked.is_dir() || (current.dev(), current.ino()) != (locked.dev(), locked.ino()) {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
"log directory changed during initialization",
|
||||
));
|
||||
}
|
||||
std::sync::Arc::new(directory)
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
path: path.to_path_buf(),
|
||||
#[cfg(unix)]
|
||||
_cleanup_lock: directory,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user