Skip to content

Commit 972ded0

Browse files
committed
Make threadsafe access to Processes and remove own unused Kill
1 parent db82213 commit 972ded0

File tree

3 files changed

+34
-29
lines changed

3 files changed

+34
-29
lines changed

modules/process/manager.go

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"fmt"
1313
"io"
1414
"os/exec"
15+
"sort"
1516
"sync"
1617
"time"
1718
)
@@ -43,14 +44,14 @@ type Manager struct {
4344
mutex sync.Mutex
4445

4546
counter int64
46-
Processes map[int64]*Process
47+
processes map[int64]*Process
4748
}
4849

4950
// GetManager returns a Manager and initializes one as singleton if there's none yet
5051
func GetManager() *Manager {
5152
if manager == nil {
5253
manager = &Manager{
53-
Processes: make(map[int64]*Process),
54+
processes: make(map[int64]*Process),
5455
}
5556
}
5657
return manager
@@ -60,7 +61,7 @@ func GetManager() *Manager {
6061
func (pm *Manager) Add(description string, cmd *exec.Cmd, cancel context.CancelFunc) int64 {
6162
pm.mutex.Lock()
6263
pid := pm.counter + 1
63-
pm.Processes[pid] = &Process{
64+
pm.processes[pid] = &Process{
6465
PID: pid,
6566
Description: description,
6667
Start: time.Now(),
@@ -76,20 +77,32 @@ func (pm *Manager) Add(description string, cmd *exec.Cmd, cancel context.CancelF
7677
// Remove a process from the ProcessManager.
7778
func (pm *Manager) Remove(pid int64) {
7879
pm.mutex.Lock()
79-
delete(pm.Processes, pid)
80+
delete(pm.processes, pid)
8081
pm.mutex.Unlock()
8182
}
8283

8384
// Cancel a process in the ProcessManager.
8485
func (pm *Manager) Cancel(pid int64) {
8586
pm.mutex.Lock()
86-
process, ok := pm.Processes[pid]
87+
process, ok := pm.processes[pid]
8788
pm.mutex.Unlock()
8889
if ok {
8990
process.Cancel()
9091
}
9192
}
9293

94+
// Processes gets the processes in a thread safe manner
95+
func (pm *Manager) Processes() []*Process {
96+
pm.mutex.Lock()
97+
processes := make([]*Process, 0, len(pm.processes))
98+
for _, process := range pm.processes {
99+
processes = append(processes, process)
100+
}
101+
pm.mutex.Unlock()
102+
sort.Sort(processList(processes))
103+
return processes
104+
}
105+
93106
// Exec a command and use the default timeout.
94107
func (pm *Manager) Exec(desc, cmdName string, args ...string) (string, string, error) {
95108
return pm.ExecDir(-1, "", desc, cmdName, args...)
@@ -152,24 +165,16 @@ func (pm *Manager) ExecDirEnvStdIn(timeout time.Duration, dir, desc string, env
152165
return stdOut.String(), stdErr.String(), err
153166
}
154167

155-
// Kill and remove a process from list.
156-
func (pm *Manager) Kill(pid int64) error {
157-
if proc, exists := pm.Processes[pid]; exists {
158-
pm.mutex.Lock()
159-
if proc.Cancel != nil {
160-
proc.Cancel()
161-
}
162-
if proc.Cmd != nil &&
163-
proc.Cmd.Process != nil &&
164-
proc.Cmd.ProcessState != nil &&
165-
!proc.Cmd.ProcessState.Exited() {
166-
if err := proc.Cmd.Process.Kill(); err != nil {
167-
return fmt.Errorf("failed to kill process(%d/%s): %v", pid, proc.Description, err)
168-
}
169-
}
170-
delete(pm.Processes, pid)
171-
pm.mutex.Unlock()
172-
}
168+
type processList []*Process
169+
170+
func (l processList) Len() int {
171+
return len(l)
172+
}
173+
174+
func (l processList) Less(i, j int) bool {
175+
return l[i].PID < l[j].PID
176+
}
173177

174-
return nil
178+
func (l processList) Swap(i, j int) {
179+
l[i], l[j] = l[j], l[i]
175180
}

modules/process/manager_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
)
1111

1212
func TestManager_Add(t *testing.T) {
13-
pm := Manager{Processes: make(map[int64]*Process)}
13+
pm := Manager{processes: make(map[int64]*Process)}
1414

1515
pid := pm.Add("foo", exec.Command("foo"), nil)
1616
assert.Equal(t, int64(1), pid, "expected to get pid 1 got %d", pid)
@@ -20,7 +20,7 @@ func TestManager_Add(t *testing.T) {
2020
}
2121

2222
func TestManager_Cancel(t *testing.T) {
23-
pm := Manager{Processes: make(map[int64]*Process)}
23+
pm := Manager{processes: make(map[int64]*Process)}
2424

2525
ctx, cancel := context.WithCancel(context.Background())
2626
pid := pm.Add("foo", exec.Command("foo"), cancel)
@@ -35,7 +35,7 @@ func TestManager_Cancel(t *testing.T) {
3535
}
3636

3737
func TestManager_Remove(t *testing.T) {
38-
pm := Manager{Processes: make(map[int64]*Process)}
38+
pm := Manager{processes: make(map[int64]*Process)}
3939

4040
pid1 := pm.Add("foo", exec.Command("foo"), nil)
4141
assert.Equal(t, int64(1), pid1, "expected to get pid 1 got %d", pid1)
@@ -45,7 +45,7 @@ func TestManager_Remove(t *testing.T) {
4545

4646
pm.Remove(pid2)
4747

48-
_, exists := pm.Processes[pid2]
48+
_, exists := pm.processes[pid2]
4949
assert.False(t, exists, "PID %d is in the list but shouldn't", pid2)
5050
}
5151

routers/admin/admin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ func Monitor(ctx *context.Context) {
352352
ctx.Data["Title"] = ctx.Tr("admin.monitor")
353353
ctx.Data["PageIsAdmin"] = true
354354
ctx.Data["PageIsAdminMonitor"] = true
355-
ctx.Data["Processes"] = process.GetManager().Processes
355+
ctx.Data["Processes"] = process.GetManager().Processes()
356356
ctx.Data["Entries"] = cron.ListTasks()
357357
ctx.HTML(200, tplMonitor)
358358
}

0 commit comments

Comments
 (0)