All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 24s
				
			Test / Sandbox (push) Successful in 46s
				
			Test / Hakurei (push) Successful in 2m9s
				
			Test / Sandbox (race detector) (push) Successful in 3m14s
				
			Test / Planterette (push) Successful in 3m41s
				
			Test / Hakurei (race detector) (push) Successful in 3m40s
				
			Test / Flake checks (push) Successful in 1m18s
				
			Signed-off-by: Ophestra <cat@gensokyo.uk>
		
			
				
	
	
		
			85 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package helper
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"errors"
 | 
						|
	"io"
 | 
						|
	"os"
 | 
						|
	"os/exec"
 | 
						|
	"slices"
 | 
						|
	"sync"
 | 
						|
	"syscall"
 | 
						|
 | 
						|
	"hakurei.app/helper/proc"
 | 
						|
)
 | 
						|
 | 
						|
// NewDirect initialises a new direct Helper instance with wt as the null-terminated argument writer.
 | 
						|
// Function argF returns an array of arguments passed directly to the child process.
 | 
						|
func NewDirect(
 | 
						|
	ctx context.Context,
 | 
						|
	name string,
 | 
						|
	wt io.WriterTo,
 | 
						|
	stat bool,
 | 
						|
	argF func(argsFd, statFd int) []string,
 | 
						|
	cmdF func(cmd *exec.Cmd),
 | 
						|
	extraFiles []*os.File,
 | 
						|
) Helper {
 | 
						|
	d, args := newHelperCmd(ctx, name, wt, stat, argF, extraFiles)
 | 
						|
	d.Args = append(d.Args, args...)
 | 
						|
	if cmdF != nil {
 | 
						|
		cmdF(d.Cmd)
 | 
						|
	}
 | 
						|
	return d
 | 
						|
}
 | 
						|
 | 
						|
func newHelperCmd(
 | 
						|
	ctx context.Context,
 | 
						|
	name string,
 | 
						|
	wt io.WriterTo,
 | 
						|
	stat bool,
 | 
						|
	argF func(argsFd, statFd int) []string,
 | 
						|
	extraFiles []*os.File,
 | 
						|
) (cmd *helperCmd, args []string) {
 | 
						|
	cmd = new(helperCmd)
 | 
						|
	cmd.helperFiles, args = newHelperFiles(ctx, wt, stat, argF, extraFiles)
 | 
						|
	cmd.Cmd = exec.CommandContext(ctx, name)
 | 
						|
	cmd.Cmd.Cancel = func() error { return cmd.Process.Signal(syscall.SIGTERM) }
 | 
						|
	cmd.WaitDelay = WaitDelay
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// helperCmd provides a [exec.Cmd] wrapper around helper ipc.
 | 
						|
type helperCmd struct {
 | 
						|
	mu sync.RWMutex
 | 
						|
	*helperFiles
 | 
						|
	*exec.Cmd
 | 
						|
}
 | 
						|
 | 
						|
func (h *helperCmd) Start() error {
 | 
						|
	h.mu.Lock()
 | 
						|
	defer h.mu.Unlock()
 | 
						|
 | 
						|
	// Check for doubled Start calls before we defer failure cleanup. If the prior
 | 
						|
	// call to Start succeeded, we don't want to spuriously close its pipes.
 | 
						|
	if h.Cmd != nil && h.Cmd.Process != nil {
 | 
						|
		return errors.New("helper: already started")
 | 
						|
	}
 | 
						|
 | 
						|
	h.Env = slices.Grow(h.Env, 2)
 | 
						|
	if h.useArgsFd {
 | 
						|
		h.Env = append(h.Env, HakureiHelper+"=1")
 | 
						|
	} else {
 | 
						|
		h.Env = append(h.Env, HakureiHelper+"=0")
 | 
						|
	}
 | 
						|
	if h.useStatFd {
 | 
						|
		h.Env = append(h.Env, HakureiStatus+"=1")
 | 
						|
 | 
						|
		// stat is populated on fulfill
 | 
						|
		h.Cancel = func() error { return h.stat.Close() }
 | 
						|
	} else {
 | 
						|
		h.Env = append(h.Env, HakureiStatus+"=0")
 | 
						|
	}
 | 
						|
 | 
						|
	return proc.Fulfill(h.helperFiles.ctx, &h.ExtraFiles, h.Cmd.Start, h.files, h.extraFiles)
 | 
						|
}
 |