posix)//src/developer/debug/debug_agent/posix provides low-level, allocation-free POSIX and Linux system call utilities for debug_agent. It includes signal-safe EINTR retry macros, a non-allocating Linux directory reader (getdents64), and an injective file-descriptor table shuffler safe for post-fork execution.
Public headers expose these types, macros, and functions:
linux::linux_dirent: 64-bit directory entry structure for getdents64 (dir_reader_linux.h).linux::DirReaderLinux: Non-copyable, fixed-buffer Linux directory reader (DirReaderLinux(const char* directory_path), IsValid(), Next(), name(), fd(), IsFallback()) (dir_reader_linux.h).HANDLE_EINTR(x): Macro that retries POSIX expression x while it returns -1 with errno == EINTR (eintr_wrapper.h).IGNORE_EINTR(x): Macro that evaluates POSIX expression x once and converts a -1 return with errno == EINTR to 0 (eintr_wrapper.h).posix::InjectionDelegate: Abstract interface (Duplicate, Move, Close) for file-descriptor table operations (file_descriptor_shuffle.h).posix::FileDescriptorTableInjection: Default InjectionDelegate implementation backed by dup, dup2, and close (file_descriptor_shuffle.h).posix::InjectionArc / posix::InjectiveMultimap: Mapping element (source, dest, close_source) and vector defining an injective file-descriptor remapping (file_descriptor_shuffle.h).posix::PerformInjectiveMultimap(const InjectiveMultimap& map, InjectionDelegate* delegate): Non-destructive wrapper that copies map and executes the descriptor remapping (file_descriptor_shuffle.h).posix::PerformInjectiveMultimapDestructive(InjectiveMultimap* map, InjectionDelegate* delegate): Allocation-free, lock-free file-descriptor remapping algorithm (file_descriptor_shuffle.h).posix::ShuffleFileDescriptors(InjectiveMultimap* map): Entry point that applies PerformInjectiveMultimapDestructive with FileDescriptorTableInjection (file_descriptor_shuffle.h).Callers and implementations must preserve these invariants:
linux::DirReaderLinux is non-copyable and performs no dynamic memory allocations. It uses a fixed 512-byte buffer aligned to linux_dirent so it remains safe in post-fork child processes.linux::DirReaderLinux::name() returns nullptr before the first successful call to Next() (when size_ == 0).HANDLE_EINTR(x) retries x while x returns -1 with errno == EINTR. In non-NDEBUG builds, HANDLE_EINTR(x) caps retries at 100 iterations to catch stuck signal loops.IGNORE_EINTR(x) evaluates x once without retrying and converts a -1 return with errno == EINTR into 0.posix::PerformInjectiveMultimapDestructive and posix::ShuffleFileDescriptors never allocate memory or acquire locks, making them safe in post-fork contexts.posix::PerformInjectiveMultimapDestructive requires unique destination descriptors in InjectiveMultimap (FX_DCHECK(i->dest != j->dest)).posix::FileDescriptorTableInjection::Close asserts via FX_DCHECK that IGNORE_EINTR(close(fd)) returns 0.These utilities produce the following OS and memory side effects:
linux::DirReaderLinux opens directory_path with O_RDONLY | O_DIRECTORY on construction, calls syscall(__NR_getdents64, ...) in Next(), and closes fd_ on destruction.posix::PerformInjectiveMultimapDestructive and posix::ShuffleFileDescriptors mutate the passed InjectiveMultimap in place as they update temporary descriptors and close flags.posix::FileDescriptorTableInjection mutates the process file-descriptor table via dup, dup2, and close system calls.Run these commands to build and test posix:
fx build //src/developer/debug/debug_agent:libfx test --host debug_agent_unit_tests