Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Freebsdcpud #289

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions cmds/cpud/init_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2018-2022 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This is init code for the case that cpu finds itself as pid 1.
// This is duplicative of the real init, but we're implementing it
// as a duplicate so we can get some idea of:
// what an init package should have
// what an init interface should have
// So we take a bit of duplication now to better understand these
// things. We also assume for now this is a busybox environment.
// It is unusual (I guess?) for cpu to be an init in anything else.
// So far, the case for an init pkg is not as strong as I thought
// it might be.
package main

import (
"log"
"runtime"
"syscall"
"time"

"github.com/u-root/u-root/pkg/libinit"
)

func cpuSetup() error {
// The process reaper runs from here, and needs to run
// as PID 1.
runtime.LockOSThread()
log.Printf(`

#### ##### # # ##
# # # # # # ##
# # # # # ##
# ##### # # ##
# # # # #
#### # #### ##
`)
// libinit.SetEnv()
// libinit.CreateRootfs()
libinit.NetInit()
// Wait for orphans, forever.
// Since there is no way of knowning when we are
// done for good, our work here is never done.
// A complication is that for long periods of time, there
// may be no orphans.In that case, sleep for one second,
// and try again. This background load is hardly enough
// to matter. And, in general, it will happen by definition
// when there is nothing to wait for, i.e. there is nothing
// on the node to be upset about.
// Were this ever to be a concern, an option is to kick off
// a process that will never exit, such that wait4 will always
// block and always return when any child process exits.
go func() {
var numReaped int
for {
var (
s syscall.WaitStatus
r syscall.Rusage
)
p, err := syscall.Wait4(-1, &s, 0, &r)
// Once per second, Wait 4 returns if there's nothing
// else to do.
if err != nil && err.Error() == "no child processes" {
continue
}
verbose("orphan reaper: returns with %v", p)
if p == -1 {
verbose("Nothing to wait for, %d wait for so far", numReaped)
time.Sleep(time.Second)
}
if err != nil {
log.Printf("CPUD: a process exited with %v, status %v, rusage %v, err %v", p, s, r, err)
}
numReaped++
}
}()

runtime.UnlockOSThread()
return nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how this function can return an error. But is this more or less duplicate, I think it's fine.

}
131 changes: 131 additions & 0 deletions cmds/cpud/main_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Copyright 2018-2019 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
"flag"
"log"
"os"
"time"

// We use this ssh because it implements port redirection.
// It can not, however, unpack password-protected keys yet.

"github.com/u-root/cpu/session"
)

var (
// For the ssh server part
hostKeyFile = flag.String("hk", "" /*"/etc/ssh/ssh_host_rsa_key"*/, "file for host key")
pubKeyFile = flag.String("pk", "key.pub", "file for public key")
port = flag.String("sp", "17010", "cpu default port")

debug = flag.Bool("d", false, "enable debug prints")
runAsInit = flag.Bool("init", false, "run as init (Debug only; normal test is if we are pid 1")
// v allows debug printing.
// Do not call it directly, call verbose instead.
v = func(string, ...interface{}) {}
remote = flag.Bool("remote", false, "indicates we are the remote side of the cpu session")
network = flag.String("net", "tcp", "network to use")
port9p = flag.String("port9p", "", "port9p # on remote machine for 9p mount")
klog = flag.Bool("klog", false, "Log cpud messages in kernel log, not stdout")

// Some networks are not well behaved, and for them we implement registration.
registerAddr = flag.String("register", "", "address and port to register with after listen on cpu server port")
registerTO = flag.Duration("registerTO", time.Duration(5*time.Second), "time.Duration for Dial address for registering")

// if we start up too quickly, mDNS won't work correctly.
// This sleep may be useful for other cases, so it is here,
// not specifically for mDNS uses.
sleepBeforeServing = flag.Duration("sleepBeforeServing", 0, "add a sleep before serving -- usually only needed if cpud runs as init with mDNS")

pid1 bool
)

func verbose(f string, a ...interface{}) {
if *remote {
v("CPUD(remote):"+f+"\r\n", a...)
} else {
v("CPUD:"+f, a...)
}
}

// There are three distinct cases to cover.
// 1. running as init (indicated by pid == 1 OR -init=true switch
// 2. running as server. pid != 1 AND -remote=true AND -init=false
// 3. running as 'remote', i.e. the thing that starts a command for
// a client. Indicated by remote=true.
//
// case (3) overrides case 2 and 1.
// This has evolved over the years, and, likely, the init and remote
// switches ought to be renamed to 'role'. But so it goes.
// The rules on arguments are very strict now. In the remote case,
// os.Args[1] MUST be remote; no other invocation is accepted, because
// the args to remote and the args to server are different.
// This invocation requirement is known to the server package.
func main() {
if len(os.Args) > 1 && (os.Args[1] == "-remote" || os.Args[1] == "-remote=true") {
*remote = true
}

if *remote {
// remote has far fewer args. Since they are specified by the client,
// we want to limit the set of args it can set.
flag.CommandLine = flag.NewFlagSet("cpud-remote", flag.ExitOnError)
debug = flag.Bool("d", false, "enable debug prints")
remote = flag.Bool("remote", false, "indicates we are the remote side of the cpu session")
port9p = flag.String("port9p", "", "port9p # on remote machine for 9p mount")

flag.Parse()
if *debug {
v = log.Printf
session.SetVerbose(verbose)
}
// If we are here, no matter what they may set, *remote must be true.
// sadly, cpud -d -remote=true -remote=false ... works.
*remote = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no sure if I get this, but for me line 69 defines remote value, maybe we should not parse it at all? I mean remove remote = flag.Bool("remote", false, "indicates we are the remote side of the cpu session")

} else {
flag.Parse()
// If we are here, no matter what they may set, *remote must be false.
*remote = false
if err := commonsetup(); err != nil {
log.Fatal(err)
}
}
pid := os.Getpid()
pid1 = pid == 1
*runAsInit = *runAsInit || pid1
verbose("Args %v pid %d *runasinit %v *remote %v env %v", os.Args, pid, *runAsInit, *remote, os.Environ())
args := flag.Args()
if *remote {
verbose("args %q, port9p %v", args, *port9p)

// This can happen if the user gets clever and
// invokes cpu with, e.g., nothing but switches.
if len(args) == 0 {
shell, ok := os.LookupEnv("SHELL")
if !ok {
log.Fatal("No arguments and $SHELL is not set")
}
args = []string{shell}
}
s := session.New(*port9p, args[0], args[1:]...)
if err := s.Run(); err != nil {
log.Fatalf("CPUD(remote): %v", err)
}
} else {
log.Printf("CPUD:PID(%d):running as a server (a.k.a. starter of cpud's for sessions)", pid)
if *runAsInit {
log.Printf("CPUD:also running as init")
if err := initsetup(); err != nil {
log.Fatal(err)
}
}
time.Sleep(*sleepBeforeServing)
if err := serve(os.Args[0]); err != nil {
log.Fatal(err)
}
}
}
16 changes: 9 additions & 7 deletions cmds/cpud/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import (
"github.com/gliderlabs/ssh"
"github.com/mdlayher/vsock"
"github.com/u-root/cpu/server"
"github.com/u-root/u-root/pkg/ulog"
"golang.org/x/sys/unix"
)

const any = math.MaxUint32
Expand Down Expand Up @@ -65,17 +63,21 @@ func commonsetup() error {
server.SetVerbose(verbose)
v = log.Printf
if *klog {
ulog.KernelLog.Reinit()
v = ulog.KernelLog.Printf
//ulog.KernelLog.Reinit()
log.Panicf("klog: not yet")
//v = ulog.KernelLog.Printf
}
}
return nil
}

func initsetup() error {
if err := unix.Mount("cpu", "/tmp", "tmpfs", 0, ""); err != nil {
log.Printf("CPUD:Warning: tmpfs mount on /tmp (%v) failed. There will be no 9p mount", err)
}
// no tmpfs in freebsd?
/*
if err := unix.Mount("cpu", "/tmp", "tmpfs", 0, ""); err != nil {
log.Printf("CPUD:Warning: tmpfs mount on /tmp (%v) failed. There will be no 9p mount", err)
}
*/
if err := cpuSetup(); err != nil {
log.Printf("CPUD:CPU setup error with cpu running as init: %v", err)
}
Expand Down
4 changes: 0 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ require (
github.com/creack/pty v1.1.18
github.com/go-git/go-billy/v5 v5.5.1-0.20240514075308-8f1b719cb6a2
github.com/google/uuid v1.6.0
github.com/hashicorp/go-multierror v1.1.1
github.com/jacobsa/fuse v0.0.0-20240909130001-a1c7c8268f12
github.com/jacobsa/syncutil v0.0.0-20180201203307-228ac8e5a6c3
github.com/mdlayher/vsock v1.2.1
github.com/moby/sys/mountinfo v0.7.1
github.com/shirou/gopsutil v3.21.11+incompatible
Expand All @@ -32,7 +29,6 @@ require (
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
Expand Down
12 changes: 0 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,13 @@ github.com/google/goexpect v0.0.0-20191001010744-5b6988669ffa h1:PMkmJA8ju9DjqAJ
github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2 h1:CVuJwN34x4xM2aT4sIKhmeib40NeBPhRihNjQmpJsA4=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hugelgupf/p9 v0.2.1-0.20230814004337-e6037077d6dc h1:rYjeymvczXx9XLtaZRRSp/DMYKVXV1QZiCbaimPxAmY=
github.com/hugelgupf/p9 v0.2.1-0.20230814004337-e6037077d6dc/go.mod h1:QFmcCPNn66imQcu1wUqJ8sHKxYjs00Gq60QLjt9E+VI=
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8=
github.com/jacobsa/fuse v0.0.0-20240909130001-a1c7c8268f12 h1:PIkShcSGp+IJB3h3Du/hNtrvug0b0o88p9pW8GF9xcg=
github.com/jacobsa/fuse v0.0.0-20240909130001-a1c7c8268f12/go.mod h1:JYi9iIxdYNgxmMgLwtSHO/hmVnP2kfX1oc+mtx+XWLA=
github.com/jacobsa/oglematchers v0.0.0-20150720000706-141901ea67cd h1:9GCSedGjMcLZCrusBZuo4tyKLpKUPenUUqi34AkuFmA=
github.com/jacobsa/oglemock v0.0.0-20150831005832-e94d794d06ff h1:2xRHTvkpJ5zJmglXLRqHiZQNjUoOkhUyhTAhEQvPAWw=
github.com/jacobsa/ogletest v0.0.0-20170503003838-80d50a735a11 h1:BMb8s3ENQLt5ulwVIHVDWFHp8eIXmbfSExkvdn9qMXI=
github.com/jacobsa/reqtrace v0.0.0-20150505043853-245c9e0234cb h1:uSWBjJdMf47kQlXMwWEfmc864bA1wAC+Kl3ApryuG9Y=
github.com/jacobsa/syncutil v0.0.0-20180201203307-228ac8e5a6c3 h1:+gHfvQxomE6fI4zg7QYyaGDCnuw2wylD4i6yzrQvAmY=
github.com/jacobsa/syncutil v0.0.0-20180201203307-228ac8e5a6c3/go.mod h1:mPvulh9VKXvo+yOlrD4VYOOYuLdZJ36wa/5QIrtXvWs=
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
Expand All @@ -48,7 +37,6 @@ github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
Expand Down
28 changes: 28 additions & 0 deletions server/server_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2018-2022 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package server

import (
"os"
"os/exec"
)

// cpud can run in one of three modes
// o init
// o daemon started by init
// o manager of one cpu session.
func init() {
// placeholder. It's not clear we ever want to do this. We used to create
// a root file system here, but that should be up to the server. The files
// might magically exist, b/c of initrd; or be automagically mounted via
// some other mechanism.
if os.Getpid() == 1 {
verbose("PID 1")
}
}

func command(n string, args ...string) *exec.Cmd {
return exec.Command(n, args...)
}
4 changes: 2 additions & 2 deletions server/server_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build !linux
// +build !linux
//go:build !linux && !freebsd
// +build !linux,!freebsd

package server

Expand Down
19 changes: 19 additions & 0 deletions session/session_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2018-2022 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package session

// Namespace does nothing; no 9p on freebsd yet.
func (s *Session) Namespace() error {
return nil
}

func osMounts() error {
return nil
}

// runSetup performs kernel-specific operations for starting a Session.
func runSetup() error {
return nil
}
3 changes: 1 addition & 2 deletions session/session_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build !linux
// +build !linux
//go:build !linux && !freebsd

package session

Expand Down
Loading