Documentation
¶
Overview ¶
Package daemon runs the watch loop as a background process and enforces a single running instance per machine. The lock is a real OS advisory file lock (flock on unix, LockFileEx on Windows) held for the process lifetime, so it is released automatically if the process dies and is immune to pid reuse. The file's contents are the holder's pid and a random per-run token, kept as metadata for stop/status and rechecked before forceful termination.
Index ¶
Constants ¶
const ( // LogMaxBytes keeps the active daemon log useful without letting a // workstation process consume unbounded disk space. LogMaxBytes int64 = 5 << 20 // LogBackups is the number of complete rotated daemon logs retained beside // the active file. LogBackups = 3 )
const ( // DefaultStopTimeout bounds both the graceful wait and, when requested, the // confirmation wait after forceful termination. DefaultStopTimeout = 10 * time.Second )
Variables ¶
var ( ErrNotRunning = errors.New("not running") ErrShutdownTimeout = errors.New("graceful shutdown timed out") ErrForceTimeout = errors.New("forced shutdown timed out") ErrProcessChanged = errors.New("daemon identity changed during shutdown") )
var ErrAlreadyRunning = errors.New("another akari instance is already running")
ErrAlreadyRunning reports lock contention from another daemon instance.
Functions ¶
func IsRunning ¶
IsRunning reports whether an instance currently holds the lock without creating the pidfile or changing its contents. Only lock contention means running; permission, filesystem, lock, and close failures remain visible.
Types ¶
type Lock ¶
type Lock struct {
// contains filtered or unexported fields
}
Lock is a held single-instance lock.
func Acquire ¶
Acquire takes the lock. It returns ErrAlreadyRunning when another live instance holds it; other filesystem and lock failures preserve their causes. The OS releases the lock automatically when this process exits, so there is no stale-lock reclaim logic and no TOCTOU window.
func (*Lock) Release ¶
Release drops the OS lock by closing the file handle. It deliberately does not remove the pidfile: unlinking after unlocking opens a window in which another process acquires the lock and we then delete the path out from under it, allowing two holders. A lingering unlocked pidfile is harmless because IsRunning probes the live lock, not the file's existence.
func (*Lock) ShutdownContext ¶ added in v0.5.5
ShutdownContext adds the daemon's local control channel to parent. A valid stop request cancels the returned context, letting the ordinary watch cleanup path release every resource before the process exits.
type Paths ¶
Paths locates the daemon's pidfile (also the lock) and its log file.
func DefaultPaths ¶
DefaultPaths returns the per-user daemon paths under the config directory.
type RotatingLog ¶ added in v0.5.5
type RotatingLog struct {
// contains filtered or unexported fields
}
RotatingLog is the sole writer for a daemon log. Rotation closes the active handle before renaming it, which is required while the daemon is running on Windows. The mutex keeps each Write and its rotation handoff indivisible.
func OpenLog ¶ added in v0.5.5
func OpenLog(path string) (*RotatingLog, error)
OpenLog opens the built-in daemon's bounded, owner-only log set.
func (*RotatingLog) Close ¶ added in v0.5.5
func (l *RotatingLog) Close() error
Close flushes and closes the active log. It is safe to call more than once.
func (*RotatingLog) Write ¶ added in v0.5.5
func (l *RotatingLog) Write(p []byte) (int, error)
Write appends all bytes in order, rotating before a record would cross the size boundary. An unusually large single write is split across bounded files without dropping bytes that still fit within the retained history.
When rotation fails, the record that triggered it is dropped rather than written through: writing through would defeat the disk bound rotation exists to enforce. The drop is not silent, though. It is counted, and as soon as a rotation next succeeds (in this call or a later one), or a plain write finds a drop still unreported, a synthesized notice line is written ahead of the caller's record so an operator reading the log can see how much was lost and why.
type StopOptions ¶ added in v0.5.5
StopOptions controls the bounded stop sequence.
type StopResult ¶ added in v0.5.5
type StopResult int
StopResult reports how a confirmed stop completed.
const ( StoppedGracefully StopResult = iota StoppedForcefully )
func Stop ¶
func Stop(p Paths, opts StopOptions) (StopResult, error)
Stop requests graceful shutdown and does not succeed until the daemon lock is free. Force permits escalation after a failed request or timeout; the recorded per-run identity is revalidated immediately before terminating the process.