pidfile

package
v3.0.0-alpha.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 5, 2026 License: BSD-2-Clause Imports: 10 Imported by: 0

Documentation

Overview

Package pidfile implements the ownership of the pid files tt writes.

A pid file holds the decimal pid without a newline, the format tt instance stop and tt instance status read; reading one never waits for its lock, and Owner tells a reader whether it is owned. Owning one means holding an exclusive flock on it, taken without blocking and kept for as long as the pid in it is current. The lock descriptor is close-on-exec, so no child inherits it, and the kernel drops it when the owner dies, however it dies.

A file whose lock stays held is refused; a lock held for a moment, by Owner probing the file, is waited out. A file nobody holds is stale and is taken over in place, under the lock, unless it names a live process: that is either a writer that has exited and left the file to name the process it started (see File.Keep), or a tt that does not lock pid files. Of any number of processes racing for one pid file, exactly one owns it. An owner unlinks the file before it unlocks it, and a process that locked a file no longer at the path starts over, so ownership never passes to an unlinked file. A file is removed only by its owner, or under the lock by RemoveFor, and only while the path still names the file that was locked.

The ownership is exclusive among the processes that follow this protocol, so every tt writer and remover of a pid file goes through this package. A process outside tt that writes or removes the same path, removes a file it has found stale without locking it, or removes the path unconditionally, is outside the guarantee and can unlink the file of a new owner.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrBusy is wrapped by the error for a pid file that another running
	// process owns.
	ErrBusy = errors.New("the pid file belongs to a running process")
)

Functions

func Alive

func Alive(path string) (int, bool, error)

Alive returns the pid the file at path names and whether that process is alive, judged as Acquire judges it before taking a file over: a process this one may not signal is alive too. A missing file, or one that names no pid, names no live process.

The file is read without the lock, so the answer can be out of date by the time the caller acts on it, and it is not for deciding who owns the file. It is for a file whose lock does not follow the process it names: one left by File.Keep, or the pid file of a child its owner wrote, which the child may outlive, such as process.pid of an external process. Whether the process that owns a file runs, such as the watchdog of an instance, Owner tells: the pid in a file its owner left may name another process by now.

func Owner

func Owner(path string) (int, bool, error)

Owner returns the pid the file at path names and whether a process owns the file, holding its lock. A missing file names no pid and is owned by nobody; so does a file that holds no pid, unless its lock is held.

A file nobody holds is stale whatever process the pid in it names now: the kernel drops the lock of an owner however it dies, while the file stays, and its pid may have been taken since by an unrelated process, after a reboot above all. For a pid file every writer of which owns it for as long as the pid in it is current, such as the pid file of the watchdog of an instance, a file nobody holds means that its process is gone, which Alive cannot tell. That does not hold for a file left by File.Keep: it is unlocked while the process it names runs.

The lock is probed without waiting: a shared lock taken on a descriptor opened for reading and dropped at once. The pid of a file nobody holds is read under that lock, which no owner writes past, and only once the path is checked to still name the file locked: a file its owner has just released counts as missing rather than stale. The pid of an owned file is read without the lock, as Alive reads it.

The probe holds the lock for a moment, which Acquire and RemoveFor wait out rather than take the file for owned (busyWait), so probing a file does not keep a process from owning it. The answer can be out of date by the time the caller acts on it: an owner may come or go right after. A caller that removes a stale file does it with RemoveFor, which checks the file again under the lock.

func RemoveFor

func RemoveFor(path string, pid int, wait time.Duration, cleanup func()) (bool, error)

RemoveFor removes the pid file at path if it still names pid, taking the lock first. It is for the pid file of a process that is gone, killed or not, whose lock the kernel drops once the process has exited: it retries the lock for up to wait, and for busyWait at least, as Acquire does. It returns whether it removed the file. A missing file, or one that names another process, is left as it is: that is a file a newer owner wrote.

Before it removes the file, still holding the lock, RemoveFor runs a non-nil cleanup to remove what else the gone process left behind: no newer owner can exist until the file is gone, so nothing cleanup finds belongs to one. It does not run cleanup when it leaves the file.

Types

type File

type File struct {
	// contains filtered or unexported fields
}

File is a pid file this process owns.

func Acquire

func Acquire(path string, pid int) (*File, error)

Acquire takes ownership of the pid file at path and writes pid into it, creating the directory if needed. A file another process owns is refused with an error wrapping ErrBusy, once its lock has stayed busy for busyWait: a lock held for a moment, by Owner probing the file, is no owner.

func (*File) Keep

func (owned *File) Keep() error

Keep gives up the ownership and leaves the file in place, for a writer that exits while the process it wrote down goes on. The file is protected from then on only by the pid in it: Acquire refuses a file that names a live process, and takes it over once that process is gone.

func (*File) Release

func (owned *File) Release() error

Release removes the pid file, if the path still names it, and gives up the ownership. The file is unlinked before it is unlocked, so a process that locks it afterwards sees that it is gone.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL