Skip to content

Commit

Permalink
Merge pull request #5276 from slonopotamus/darwin
Browse files Browse the repository at this point in the history
Add stub implementations to make buildkitd buildable for Darwin
  • Loading branch information
tonistiigi authored Sep 16, 2024
2 parents b1abc62 + 64f4631 commit 734a6cc
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 101 deletions.
3 changes: 0 additions & 3 deletions cmd/buildkitd/main_containerd_worker.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//go:build linux || windows || freebsd
// +build linux windows freebsd

package main

import (
Expand Down
64 changes: 64 additions & 0 deletions executor/oci/spec_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package oci

import (
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/oci"
"github.com/containerd/continuity/fs"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/solver/pb"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)

func withProcessArgs(args ...string) oci.SpecOpts {
return oci.WithProcessArgs(args...)
}

func generateMountOpts(_, _ string) []oci.SpecOpts {
return nil
}

func generateSecurityOpts(mode pb.SecurityMode, _ string, _ bool) ([]oci.SpecOpts, error) {
return nil, nil
}

func generateProcessModeOpts(mode ProcessMode) ([]oci.SpecOpts, error) {
return nil, nil
}

func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
if idmap == nil {
return nil, nil
}
return nil, errors.New("no support for IdentityMapping on Darwin")
}

func generateRlimitOpts(ulimits []*pb.Ulimit) ([]oci.SpecOpts, error) {
if len(ulimits) == 0 {
return nil, nil
}
return nil, errors.New("no support for POSIXRlimit on Darwin")
}

// tracing is not implemented on Darwin
func getTracingSocketMount(_ string) *specs.Mount {
return nil
}

// tracing is not implemented on Darwin
func getTracingSocket() string {
return ""
}

func cgroupV2NamespaceSupported() bool {
return false
}

func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) {
src, err := fs.RootPath(m.Source, subPath)
if err != nil {
return mount.Mount{}, nil, err
}
m.Source = src
return m, func() error { return nil }, nil
}
67 changes: 67 additions & 0 deletions snapshot/localmounter_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package snapshot

import (
"os"

"github.com/containerd/containerd/mount"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
)

func (lm *localMounter) Mount() (string, error) {
lm.mu.Lock()
defer lm.mu.Unlock()

if lm.mounts == nil && lm.mountable != nil {
mounts, release, err := lm.mountable.Mount()
if err != nil {
return "", err
}
lm.mounts = mounts
lm.release = release
}

if len(lm.mounts) == 1 && lm.mounts[0].Type == "bind" {
ro := false
for _, opt := range lm.mounts[0].Options {
if opt == "ro" {
ro = true
break
}
}
if !ro {
return lm.mounts[0].Source, nil
}
}

dir, err := os.MkdirTemp("", "buildkit-mount")
if err != nil {
return "", errors.Wrap(err, "failed to create temp dir")
}

if err := mount.All(lm.mounts, dir); err != nil {
os.RemoveAll(dir)
return "", errors.Wrapf(err, "failed to mount %s: %+v", dir, lm.mounts)
}
lm.target = dir
return dir, nil
}

func (lm *localMounter) Unmount() error {
lm.mu.Lock()
defer lm.mu.Unlock()

if lm.target != "" {
if err := mount.UnmountRecursive(lm.target, unix.MNT_FORCE); err != nil {
return err
}
os.RemoveAll(lm.target)
lm.target = ""
}

if lm.release != nil {
return lm.release()
}

return nil
}
7 changes: 7 additions & 0 deletions source/git/source_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package git

import "golang.org/x/sys/unix"

var reexecSysProcAttr = unix.SysProcAttr{
Setpgid: true,
}
100 changes: 4 additions & 96 deletions source/git/source_freebsd.go
Original file line number Diff line number Diff line change
@@ -1,100 +1,8 @@
package git

import (
"context"
"os"
"os/exec"
"os/signal"
"syscall"
"time"
import "golang.org/x/sys/unix"

"github.com/docker/docker/pkg/reexec"
"golang.org/x/sys/unix"
)

const (
gitCmd = "umask-git"
)

func init() {
reexec.Register(gitCmd, gitMain)
}

func gitMain() {
// Need standard user umask for git process.
unix.Umask(0022)

// Reexec git command
cmd := exec.Command(os.Args[1], os.Args[2:]...) //nolint:gosec // reexec
cmd.SysProcAttr = &unix.SysProcAttr{
Setpgid: true,
Pdeathsig: unix.SIGTERM,
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin

// Forward all signals
sigc := make(chan os.Signal, 1)
done := make(chan struct{})
signal.Notify(sigc)
go func() {
for {
select {
case sig := <-sigc:
if cmd.Process == nil {
continue
}
switch sig {
case unix.SIGINT, unix.SIGTERM, unix.SIGKILL:
_ = unix.Kill(-cmd.Process.Pid, sig.(unix.Signal))
default:
_ = cmd.Process.Signal(sig)
}
case <-done:
return
}
}
}()

err := cmd.Run()
close(done)
if err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
switch status := exiterr.Sys().(type) {
case unix.WaitStatus:
os.Exit(status.ExitStatus())
case syscall.WaitStatus:
os.Exit(status.ExitStatus())
}
}
os.Exit(1)
}
os.Exit(0)
}

func runWithStandardUmask(ctx context.Context, cmd *exec.Cmd) error {
cmd.Path = reexec.Self()
cmd.Args = append([]string{gitCmd}, cmd.Args...)
if err := cmd.Start(); err != nil {
return err
}
waitDone := make(chan struct{})
go func() {
select {
case <-ctx.Done():
_ = unix.Kill(-cmd.Process.Pid, unix.SIGTERM)
go func() {
select {
case <-waitDone:
case <-time.After(10 * time.Second):
_ = unix.Kill(-cmd.Process.Pid, unix.SIGKILL)
}
}()
case <-waitDone:
}
}()
err := cmd.Wait()
close(waitDone)
return err
var reexecSysProcAttr = unix.SysProcAttr{
Setpgid: true,
Pdeathsig: unix.SIGTERM,
}
99 changes: 99 additions & 0 deletions source/git/source_unix_nolinux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//go:build unix && !linux

package git

import (
"context"
"os"
"os/exec"
"os/signal"
"syscall"
"time"

"github.com/docker/docker/pkg/reexec"
"golang.org/x/sys/unix"
)

const (
gitCmd = "umask-git"
)

func init() {
reexec.Register(gitCmd, gitMain)
}

func gitMain() {
// Need standard user umask for git process.
unix.Umask(0022)

// Reexec git command
cmd := exec.Command(os.Args[1], os.Args[2:]...) //nolint:gosec // reexec
cmd.SysProcAttr = &reexecSysProcAttr
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin

// Forward all signals
sigc := make(chan os.Signal, 1)
done := make(chan struct{})
signal.Notify(sigc)
go func() {
for {
select {
case sig := <-sigc:
if cmd.Process == nil {
continue
}
switch sig {
case unix.SIGINT, unix.SIGTERM, unix.SIGKILL:
_ = unix.Kill(-cmd.Process.Pid, sig.(unix.Signal))
default:
_ = cmd.Process.Signal(sig)
}
case <-done:
return
}
}
}()

err := cmd.Run()
close(done)
if err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
switch status := exiterr.Sys().(type) {
case unix.WaitStatus:
os.Exit(status.ExitStatus())
case syscall.WaitStatus:
os.Exit(status.ExitStatus())
}
}
os.Exit(1)
}
os.Exit(0)
}

func runWithStandardUmask(ctx context.Context, cmd *exec.Cmd) error {
cmd.Path = reexec.Self()
cmd.Args = append([]string{gitCmd}, cmd.Args...)
if err := cmd.Start(); err != nil {
return err
}
waitDone := make(chan struct{})
go func() {
select {
case <-ctx.Done():
_ = unix.Kill(-cmd.Process.Pid, unix.SIGTERM)
go func() {
select {
case <-waitDone:
case <-time.After(10 * time.Second):
_ = unix.Kill(-cmd.Process.Pid, unix.SIGKILL)
}
}()
case <-waitDone:
}
}()
err := cmd.Wait()
close(waitDone)
return err
}
4 changes: 2 additions & 2 deletions util/network/netproviders/network_nobridge.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:build freebsd || windows
// +build freebsd windows
//go:build !linux
// +build !linux

package netproviders

Expand Down

0 comments on commit 734a6cc

Please sign in to comment.