fleet/orbit/pkg/platform/platform.go
Lucas Manuel Rodriguez ba3746f9fa
Fix fleetd crash in Apple M5 hardware by upgrading gopsutil (#41940)
Resolves #41863

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.

## Testing

- [x] QA'd all new/changed functionality manually

Tests performed on the following OSs:
- Windows (arm64)
- macOS (Apple silicon)
- Linux (arm64)
- Linux (amd64)

Features tested on the OSs above:
- "My device".
- Restart fleetd.
- Kill fleet desktop, should re-start.
- Killing stale osqueryd processes on orbit startup.
- Checking if osquery is up and running, exit and start.
- Checking if Fleet Desktop is already running before launching it.
- orbit auto update
- Gracefully shutting down Fleet Desktop before restarting it

---

## fleetd/orbit/Fleet Desktop

- [X] Verified compatibility with the latest released version of Fleet
(see [Must
rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md))
- [x] If the change applies to only one platform, confirmed that
`runtime.GOOS` is used as needed to isolate changes
- [x] Verified that fleetd runs on macOS, Linux and Windows
- [x] Verified auto-update works from the released version of component
to the new version (see [tools/tuf/test](../tools/tuf/test/README.md))
2026-03-18 11:21:02 -03:00

85 lines
2.2 KiB
Go

package platform
import (
"errors"
"fmt"
"strings"
gopsutil_process "github.com/shirou/gopsutil/v4/process"
)
var (
ErrProcessNotFound = errors.New("process not found")
ErrComChannelNotFound = errors.New("comm channel not found")
)
type UUIDSource string
const (
UUIDSourceInvalid = "UUID_Source_Invalid"
UUIDSourceWMI = "UUID_Source_WMI"
UUIDSourceHardware = "UUID_Source_Hardware"
)
// getProcessesByName returns all the running processes with the given prefix in their name.
func getProcessesByName(namePrefix string) ([]*gopsutil_process.Process, error) {
if namePrefix == "" {
return nil, errors.New("process name prefix should not be empty")
}
processes, err := gopsutil_process.Processes()
if err != nil {
return nil, err
}
var foundProcesses []*gopsutil_process.Process
for _, process := range processes {
processName, err := process.Name()
if err != nil {
// No need to print errors here as this method might file for system processes
continue
}
if strings.HasPrefix(processName, namePrefix) {
foundProcesses = append(foundProcesses, process)
}
}
return foundProcesses, nil
}
// Process holds basic information of a process.
type Process struct {
// Name is the name of the process.
Name string
// PID is the process identifier.
PID int32
}
// KillAllProcessByName kills all the running processes with the given prefix in their name.
// It returns the processes that were killed. It returns `nil, nil` if there were no processes
// running with such name prefix.
func KillAllProcessByName(namePrefix string) ([]Process, error) {
if namePrefix == "" {
return nil, errors.New("process name prefix should not be empty")
}
foundProcesses, err := getProcessesByName(namePrefix)
if err != nil {
return nil, fmt.Errorf("get processes by name: %w", err)
}
var killedProcesses []Process
for _, foundProcess := range foundProcesses {
processName, _ := foundProcess.Name()
if err := foundProcess.Kill(); err != nil {
return nil, fmt.Errorf("kill process %d: %w", foundProcess.Pid, err)
}
killedProcesses = append(killedProcesses, Process{
Name: processName,
PID: foundProcess.Pid,
})
}
return killedProcesses, nil
}