diff options
Diffstat (limited to 'internal/testsuite')
| -rw-r--r-- | internal/testsuite/testsuite.go | 96 |
1 files changed, 78 insertions, 18 deletions
diff --git a/internal/testsuite/testsuite.go b/internal/testsuite/testsuite.go index c4ca23e9..367cb4c0 100644 --- a/internal/testsuite/testsuite.go +++ b/internal/testsuite/testsuite.go @@ -20,6 +20,7 @@ import ( "os/user" "path/filepath" "reflect" + "runtime" "slices" "strconv" "strings" @@ -603,6 +604,82 @@ func MustScanFor(f func(ps *StatScanner) bool) int { return ps.Stat().PID } +// storeLookup describes a store lookup request. +type storeLookup struct { + // Identifier to look up. + id hst.ID + // Address of value to write result to. + p *hst.State + // Error encountered while fulfilling the request. + done chan<- error +} + +var ( + // storeThreads holds channels for dispatching requests to goroutines + // locked to threads configured with specific credentials. + storeThreads = make(map[[2]uint32]chan<- storeLookup) + // storeThreadsMu synchronises access to storeThreads. + storeThreadsMu sync.Mutex +) + +// LookupStore looks up the specified identifier from the hakurei state store +// and stores its contents in the value pointed to by p. +func LookupStore(cred *syscall.Credential, id hst.ID, p *hst.State) error { + var key [2]uint32 + if cred != nil { + key[0], key[1] = cred.Uid, cred.Gid + } + + storeThreadsMu.Lock() + c, ok := storeThreads[key] + if !ok { + s := store.New(check.MustAbs(HakureiPrefix + "state")) + r := make(chan storeLookup) + go func() { + if cred != nil { + runtime.LockOSThread() + if err := syscall.Setfsuid(int(cred.Uid)); err != nil { + log.Fatalf("setfsuid: %v", err) + } else if err = syscall.Setfsgid(int(cred.Gid)); err != nil { + log.Fatalf("setfsgid: %v", err) + } + } + + req: + for req := range r { + ok = false + entries, copyError := s.All() + for entry := range entries { + if entry.ID == req.id { + ok = true + if _, err := entry.Load(req.p, nil); err != nil { + req.done <- err + continue req + } + break + } + } + if err := copyError(); err != nil { + req.done <- err + continue + } + if !ok { + req.done <- fmt.Errorf("instance %s is not present in store", id.String()) + continue + } + req.done <- nil + } + }() + c = r + storeThreads[key] = c + } + storeThreadsMu.Unlock() + + done := make(chan error, 1) + c <- storeLookup{id, p, done} + return <-done +} + // StartHakurei starts a hakurei container configured by c. func StartHakurei( ctx context.Context, @@ -614,8 +691,6 @@ func StartHakurei( scan, wait, verbose, insecure bool, c *hst.Config, ) (p hst.State, pid int, err error) { - s := store.New(check.MustAbs("/tmp/hakurei.0/state")) - var hakureiFlags string if verbose { hakureiFlags += " -v" @@ -732,22 +807,7 @@ func StartHakurei( "hakurei", "--json", "show", id.String(), ) - var ok bool - entries, copyError := s.All() - for entry := range entries { - if entry.ID == id { - ok = true - if _, err = entry.Load(&p, nil); err != nil { - return - } - break - } - } - if err = copyError(); err != nil { - log.Fatal(err) - } - if !ok { - err = fmt.Errorf("instance %s is not present in store", id.String()) + if err = LookupStore(cred, id, &p); err != nil { return } |
