platform: Fix daemon data

This commit is contained in:
世界
2026-07-13 15:42:06 +08:00
parent a8a69228d8
commit f505a47bca
7 changed files with 217 additions and 148 deletions
+70 -63
View File
@@ -24,23 +24,22 @@ import (
"google.golang.org/grpc/status"
)
const daemonCrashOutputFileName = "CrashReport-Daemon.log"
type Daemon struct {
logger log.ContextLogger
startedService *daemon.StartedService
server *grpc.Server
listenerPath string
lifecycleAccess sync.Mutex
closed bool
peerAccess sync.Mutex
peerConnections map[peerConnection]peerIdentity
logger log.ContextLogger
startedService *daemon.StartedService
server *grpc.Server
runtimeWorkingDirectory string
lifecycleAccess sync.Mutex
closed bool
peerAccess sync.Mutex
peerConnections map[peerConnection]peerIdentity
}
func newDaemon() (*Daemon, error) {
ctx := include.Context(context.Background())
d := &Daemon{
logger: log.StdLogger(),
logger: log.StdLogger(),
runtimeWorkingDirectory: workingDirectory,
}
d.startedService = daemon.NewStartedService(daemon.ServiceOptions{
Context: ctx,
@@ -91,13 +90,6 @@ func (d *Daemon) Start() error {
if err != nil {
return err
}
if listener.Addr().Network() == "unix" {
d.listenerPath, err = filepath.Abs(listener.Addr().String())
if err != nil {
listener.Close()
return err
}
}
d.logger.Info("daemon listening at ", listener.Addr())
go func() {
serveError := d.server.Serve(listener)
@@ -115,38 +107,82 @@ func (d *Daemon) restore() {
if d.closed {
return
}
options, err := loadStartOptions()
ownerUserID, err := loadOwner()
if err != nil {
if !os.IsNotExist(err) {
d.logger.Warn("load owner: ", err)
}
return
}
ownerWorkingDirectory := userWorkingDirectory(ownerUserID)
err = d.configureWorkingDirectoryLocked(ownerWorkingDirectory)
if err != nil {
d.logger.Warn("configure working directory: ", err)
return
}
options, err := loadStartOptions(ownerUserID)
if err != nil {
if !os.IsNotExist(err) {
d.logger.Warn("load start options: ", err)
}
return
}
err = tagUnownedReports(filepath.Join(workingDirectory, crashReportsDirectoryName), options.OwnerUserID)
err = tagUnownedReports(filepath.Join(ownerWorkingDirectory, crashReportsDirectoryName), ownerUserID)
if err != nil {
d.logger.Warn("tag crash reports: ", err)
}
err = tagUnownedReports(filepath.Join(workingDirectory, oomReportsDirectoryName), options.OwnerUserID)
err = tagUnownedReports(filepath.Join(ownerWorkingDirectory, oomReportsDirectoryName), ownerUserID)
if err != nil {
d.logger.Warn("tag OOM reports: ", err)
}
if !options.WasRunning {
return
}
configContent, err := loadServiceConfig()
configContent, err := loadServiceConfig(ownerUserID)
if err != nil {
d.logger.Error("restore service: ", err)
return
}
d.logger.Info("restoring service")
err = d.startService(configContent, options)
err = d.startServiceLocked(ownerUserID, configContent, options)
if err != nil {
d.logger.Error("restore service: ", err)
}
}
func (d *Daemon) startService(configContent string, options startOptions) error {
_ = os.WriteFile(filepath.Join(workingDirectory, configSnapshotFileName), []byte(configContent), 0o600)
func (d *Daemon) configureWorkingDirectoryLocked(directory string) error {
if d.runtimeWorkingDirectory == directory {
return nil
}
err := os.MkdirAll(directory, 0o700)
if err != nil {
return err
}
err = os.Chdir(directory)
if err != nil {
return err
}
err = libbox.Setup(&libbox.SetupOptions{
BasePath: directory,
WorkingPath: directory,
TempPath: directory,
CrashReportSource: "Daemon",
})
if err != nil {
return err
}
libbox.PromoteOOMDraft()
d.runtimeWorkingDirectory = directory
return nil
}
func (d *Daemon) startServiceLocked(ownerUserID string, configContent string, options startOptions) error {
directory := userWorkingDirectory(ownerUserID)
err := d.configureWorkingDirectoryLocked(directory)
if err != nil {
return err
}
_ = os.WriteFile(filepath.Join(directory, configSnapshotFileName), []byte(configContent), 0o600)
libbox.ReloadSetupOptions(&libbox.SetupOptions{
OomKillerEnabled: options.OOMKillerEnabled,
OomKillerDisabled: options.OOMKillerDisabled,
@@ -156,39 +192,8 @@ func (d *Daemon) startService(configContent string, options startOptions) error
return d.startedService.StartOrReloadService(configContent, nil)
}
func (d *Daemon) clearRuntimeData() error {
entries, err := os.ReadDir(workingDirectory)
if err != nil {
return err
}
for _, entry := range entries {
if entry.Name() == crashReportsDirectoryName ||
entry.Name() == oomReportsDirectoryName ||
entry.Name() == daemonCrashOutputFileName {
continue
}
entryPath := filepath.Join(workingDirectory, entry.Name())
if d.listenerPath != "" && entryPath == d.listenerPath {
continue
}
err = os.RemoveAll(entryPath)
if err != nil {
return err
}
}
return nil
}
func (d *Daemon) resetRuntimeOwnerLocked(ownerUserID string) error {
err := d.clearRuntimeData()
if err != nil {
return err
}
return saveStartOptions(startOptions{OwnerUserID: ownerUserID})
}
func (d *Daemon) stopServiceLocked(nextOwnerUserID string) error {
options, err := loadStartOptions()
func (d *Daemon) stopServiceLocked(ownerUserID string) error {
options, err := loadStartOptions(ownerUserID)
if err != nil && !os.IsNotExist(err) {
return err
}
@@ -198,15 +203,17 @@ func (d *Daemon) stopServiceLocked(nextOwnerUserID string) error {
return err
}
}
crashReportError := tagUnownedReports(filepath.Join(workingDirectory, crashReportsDirectoryName), options.OwnerUserID)
directory := userWorkingDirectory(ownerUserID)
crashReportError := tagUnownedReports(filepath.Join(directory, crashReportsDirectoryName), ownerUserID)
if crashReportError != nil {
return crashReportError
}
oomReportError := tagUnownedReports(filepath.Join(workingDirectory, oomReportsDirectoryName), options.OwnerUserID)
oomReportError := tagUnownedReports(filepath.Join(directory, oomReportsDirectoryName), ownerUserID)
if oomReportError != nil {
return oomReportError
}
return d.resetRuntimeOwnerLocked(nextOwnerUserID)
options.WasRunning = false
return saveStartOptions(ownerUserID, options)
}
func (d *Daemon) Close() {
@@ -311,14 +318,14 @@ func ownerProtectedMethod(method string) bool {
}
func (d *Daemon) authorizeOwnerLocked(userID string) error {
options, err := loadStartOptions()
ownerUserID, err := loadOwner()
if err != nil {
if os.IsNotExist(err) {
return status.Error(codes.PermissionDenied, "the service has no owner")
}
return err
}
if options.OwnerUserID == "" || options.OwnerUserID != userID {
if ownerUserID == "" || ownerUserID != userID {
return status.Error(codes.PermissionDenied, "the service is owned by another user")
}
return nil