diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-11-12 23:12:38 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-11-12 23:16:13 +0900 |
| commit | f347d44c2281f507e3786aa498f634bfa4c92d84 (patch) | |
| tree | fe85b41d5f6a5e308b87585f46efd64f90221e2b /helper/proc/files.go | |
| parent | b5630f6883c874d458d9ae3c666cfb7ae5e3121d (diff) | |
internal/helper: relocate from helper
This package is ugly and is pending removal only kept alive by xdg-dbus-proxy.
Its exported symbols are made available until v0.4.0 where it will be removed for #24.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'helper/proc/files.go')
| -rw-r--r-- | helper/proc/files.go | 162 |
1 files changed, 0 insertions, 162 deletions
diff --git a/helper/proc/files.go b/helper/proc/files.go deleted file mode 100644 index 0612718e..00000000 --- a/helper/proc/files.go +++ /dev/null @@ -1,162 +0,0 @@ -package proc - -import ( - "context" - "os" - "os/exec" - "sync/atomic" - "syscall" - "testing" - "time" -) - -var FulfillmentTimeout = 2 * time.Second - -func init() { - if testing.Testing() { - FulfillmentTimeout *= 10 - } -} - -// A File is an extra file with deferred initialisation. -type File interface { - // Init initialises File state. Init must not be called more than once. - Init(fd uintptr, v **os.File) uintptr - // Fd returns the fd value set on initialisation. - Fd() uintptr - // ErrCount returns count of error values emitted during fulfillment. - ErrCount() int - // Fulfill is called prior to process creation and must populate its corresponding file address. - // Calls to dispatchErr must match the return value of ErrCount. - // Fulfill must not be called more than once. - Fulfill(ctx context.Context, dispatchErr func(error)) error -} - -// ExtraFilesPre is a linked list storing addresses of [os.File]. -type ExtraFilesPre struct { - n *ExtraFilesPre - v *os.File -} - -// Append grows the list by one entry and returns an address of the address of [os.File] stored in the new entry. -func (f *ExtraFilesPre) Append() (uintptr, **os.File) { return f.append(3) } - -// Files returns a slice pointing to a continuous segment of memory containing all addresses stored in f in order. -func (f *ExtraFilesPre) Files() []*os.File { return f.copy(make([]*os.File, 0, f.len())) } - -func (f *ExtraFilesPre) append(i uintptr) (uintptr, **os.File) { - if f.n == nil { - f.n = new(ExtraFilesPre) - return i, &f.v - } - return f.n.append(i + 1) -} -func (f *ExtraFilesPre) len() uintptr { - if f == nil { - return 0 - } - return f.n.len() + 1 -} -func (f *ExtraFilesPre) copy(e []*os.File) []*os.File { - if f == nil { - // the public methods ensure the first call is never nil; - // the last element is unused, slice it off here - return e[:len(e)-1] - } - return f.n.copy(append(e, f.v)) -} - -// Fulfill calls the [File.Fulfill] method on all files, starts cmd and blocks until all fulfillment completes. -func Fulfill(ctx context.Context, - v *[]*os.File, start func() error, - files []File, extraFiles *ExtraFilesPre, -) (err error) { - var ecs int - for _, o := range files { - ecs += o.ErrCount() - } - ec := make(chan error, ecs) - - c, cancel := context.WithTimeout(ctx, FulfillmentTimeout) - defer cancel() - - for _, f := range files { - err = f.Fulfill(c, makeDispatchErr(f, ec)) - if err != nil { - return - } - } - - *v = extraFiles.Files() - if err = start(); err != nil { - return - } - - for ecs > 0 { - select { - case err = <-ec: - ecs-- - if err != nil { - break - } - case <-ctx.Done(): - err = syscall.ECANCELED - break - } - } - return -} - -// InitFile initialises f as part of the slice extraFiles points to, -// and returns its final fd value. -func InitFile(f File, extraFiles *ExtraFilesPre) (fd uintptr) { return f.Init(extraFiles.Append()) } - -// BaseFile implements the Init method of the File interface and provides indirect access to extra file state. -type BaseFile struct { - fd uintptr - v **os.File -} - -func (f *BaseFile) Init(fd uintptr, v **os.File) uintptr { - if v == nil || fd < 3 { - panic("invalid extra file initial state") - } - if f.v != nil { - panic("extra file initialised twice") - } - f.fd, f.v = fd, v - return fd -} - -func (f *BaseFile) Fd() uintptr { - if f.v == nil { - panic("use of uninitialised extra file") - } - return f.fd -} - -func (f *BaseFile) Set(v *os.File) { - *f.v = v // runtime guards against use before init -} - -func makeDispatchErr(f File, ec chan<- error) func(error) { - c := new(atomic.Int32) - c.Store(int32(f.ErrCount())) - return func(err error) { - if c.Add(-1) < 0 { - panic("unexpected error dispatches") - } - ec <- err - } -} - -func ExtraFile(cmd *exec.Cmd, f *os.File) (fd uintptr) { - return ExtraFileSlice(&cmd.ExtraFiles, f) -} - -func ExtraFileSlice(extraFiles *[]*os.File, f *os.File) (fd uintptr) { - // ExtraFiles: If non-nil, entry i becomes file descriptor 3+i. - fd = uintptr(3 + len(*extraFiles)) - *extraFiles = append(*extraFiles, f) - return -} |
