Skip to content

Commit 078c8ff

Browse files
committed
TO SQUASH OR REMOVE
1 parent 36e8a3f commit 078c8ff

File tree

4 files changed

+68
-49
lines changed

4 files changed

+68
-49
lines changed

cli/running/instance.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ type Instance struct {
5050
waitMutex sync.Mutex
5151
// done represent whether the instance was stopped.
5252
done bool
53+
// stateMutex used to avoid a race condition under started and shouldStop fields.
54+
stateMutex sync.Mutex
55+
// started indicates whether the Watchdog has started an Instance.
56+
started bool
57+
// shouldStop indicates whether the Watchdog should stop the Instance.
58+
shouldStop bool
5359
}
5460

5561
//go:embed lua/launcher.lua

cli/running/running.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -518,21 +518,17 @@ func Start(cmdCtx *cmdcontext.CmdCtx, run *InstanceCtx) error {
518518
provider := providerImpl{cmdCtx: cmdCtx, instanceCtx: run}
519519
wd := NewWatchdog(run.Restartable, 5*time.Second, logger, &provider)
520520

521-
// The signal handling loop must be started before the instance
522-
// get started for avoiding a race condition between tt start
523-
// and tt stop. This way we avoid a situation when we receive
524-
// a signal before starting a handler for it.
525-
wd.StartSignalHandling()
526-
527-
if err := process_utils.CreatePIDFile(run.PIDFile); err != nil {
528-
return err
529-
}
530-
531521
defer func() {
532522
cleanup(run)
533523
}()
534524

535-
wd.Start()
525+
preStartAction := func() error {
526+
if err := process_utils.CreatePIDFile(run.PIDFile); err != nil {
527+
return err
528+
}
529+
return nil
530+
}
531+
wd.Start(preStartAction)
536532
return nil
537533
}
538534

cli/running/watchdog.go

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ type Watchdog struct {
4242
// and updating may depend on changing external parameters
4343
// (such as configuration file).
4444
provider Provider
45-
// instanceStateMutex used to avoid a race condition under started and shouldStop fields.
46-
instanceStateMutex sync.Mutex
47-
// started indicates whether the Watchdog has started an Instance.
48-
started bool
49-
// shouldStop indicates whether the Watchdog should stop the Instance.
50-
shouldStop bool
5145
}
5246

5347
// NewWatchdog creates a new instance of Watchdog.
@@ -57,48 +51,61 @@ func NewWatchdog(restartable bool, restartTimeout time.Duration, logger *ttlog.L
5751
provider: provider}
5852

5953
wd.done = make(chan bool, 1)
60-
wd.shouldStop = false
6154

6255
return &wd
6356
}
6457

6558
// Start starts the Instance and signal handling.
66-
func (wd *Watchdog) Start() {
59+
func (wd *Watchdog) Start(preStartAction func() error) error {
60+
var err error
61+
// Create Instance.
62+
if wd.Instance, err = wd.provider.CreateInstance(wd.logger); err != nil {
63+
wd.logger.Printf(`Watchdog(ERROR): "%v".`, err)
64+
return err
65+
}
66+
wd.logger = wd.Instance.logger
67+
// The signal handling loop must be started before the instance
68+
// get started for avoiding a race condition between tt start
69+
// and tt stop. This way we avoid a situation when we receive
70+
// a signal before starting a handler for it.
71+
wd.startSignalHandling()
72+
73+
if err = preStartAction(); err != nil {
74+
wd.logger.Printf(`Pre-start action error: %v`, err)
75+
// Finish the signal handling goroutine.
76+
wd.done <- true
77+
return err
78+
}
79+
6780
// The Instance must be restarted on completion if the "restartable"
6881
// parameter is set to "true".
6982
for {
7083
var err error
71-
// Create Instance.
72-
if wd.Instance, err = wd.provider.CreateInstance(wd.logger); err != nil {
73-
wd.logger.Printf(`Watchdog(ERROR): "%v".`, err)
74-
break
75-
}
76-
wd.logger = wd.Instance.logger
7784

78-
wd.stateMutex.Lock()
79-
if !wd.shouldStop {
85+
wd.Instance.stateMutex.Lock()
86+
if !wd.Instance.shouldStop {
8087
// Start the Instance.
8188
if err := wd.Instance.Start(); err != nil {
8289
wd.logger.Printf(`Watchdog(ERROR): "%v".`, err)
83-
wd.stateMutex.Unlock()
90+
wd.Instance.stateMutex.Unlock()
8491
break
8592
}
86-
wd.started = true
93+
wd.Instance.started = true
8794
} else {
8895
wd.logger.Printf(`Watchdog(ERROR): terminated before instance start.`)
89-
wd.stateMutex.Unlock()
90-
return
96+
wd.Instance.stateMutex.Unlock()
97+
return nil
9198
}
92-
wd.stateMutex.Unlock()
99+
wd.Instance.stateMutex.Unlock()
93100

94101
// Wait while the Instance will be terminated.
95102
if err := wd.Instance.Wait(); err != nil {
96103
wd.logger.Printf(`Watchdog(WARN): "%v".`, err)
97104
}
98105

99-
wd.stateMutex.Lock()
100-
wd.started = false
101-
wd.stateMutex.Unlock()
106+
wd.Instance.stateMutex.Lock()
107+
wd.Instance.started = false
108+
wd.Instance.stateMutex.Unlock()
102109

103110
// Set Instance process completion indication.
104111
wd.done <- true
@@ -111,7 +118,7 @@ func (wd *Watchdog) Start() {
111118
wd.logger.Println("Watchdog(ERROR): can't check if the instance is restartable.")
112119
break
113120
}
114-
if wd.shouldStop || !restartable {
121+
if wd.Instance.shouldStop || !restartable {
115122
wd.logger.Println("Watchdog(INFO): the Instance has shutdown.")
116123
break
117124
}
@@ -124,14 +131,22 @@ func (wd *Watchdog) Start() {
124131
}
125132
time.Sleep(wd.restartTimeout)
126133

127-
wd.shouldStop = false
134+
wd.Instance.shouldStop = false
135+
136+
// Create Instance.
137+
if wd.Instance, err = wd.provider.CreateInstance(wd.logger); err != nil {
138+
wd.logger.Printf(`Watchdog(ERROR): "%v".`, err)
139+
return err
140+
}
141+
wd.logger = wd.Instance.logger
128142
// Before the restart of an instance start a new signal handling loop.
129-
wd.StartSignalHandling()
143+
wd.startSignalHandling()
130144
}
145+
return nil
131146
}
132147

133-
// StartSignalHandling starts signal handling in a separate goroutine.
134-
func (wd *Watchdog) StartSignalHandling() {
148+
// startSignalHandling starts signal handling in a separate goroutine.
149+
func (wd *Watchdog) startSignalHandling() {
135150
sigChan := make(chan os.Signal, 1)
136151
// Reset the signal mask before starting of the new loop.
137152
signal.Reset()
@@ -157,23 +172,23 @@ func (wd *Watchdog) StartSignalHandling() {
157172
case sig := <-sigChan:
158173
switch sig {
159174
case syscall.SIGINT, syscall.SIGTERM:
160-
wd.stateMutex.Lock()
161-
if wd.started {
175+
wd.Instance.stateMutex.Lock()
176+
if wd.Instance.started {
162177
wd.Instance.Stop(30 * time.Second)
163178
}
164179
// If we receive one of the "stop" signals, the
165180
// program should be terminated.
166-
wd.shouldStop = true
167-
wd.stateMutex.Unlock()
181+
wd.Instance.shouldStop = true
182+
wd.Instance.stateMutex.Unlock()
168183
case syscall.SIGHUP:
169184
// Rotate the log files.
170185
wd.logger.Rotate()
171186
default:
172-
wd.stateMutex.Lock()
173-
if wd.started {
187+
wd.Instance.stateMutex.Lock()
188+
if wd.Instance.started {
174189
wd.Instance.SendSignal(sig)
175190
}
176-
wd.stateMutex.Unlock()
191+
wd.Instance.stateMutex.Unlock()
177192
}
178193
case _ = <-wd.done:
179194
return

cli/running/watchdog_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,9 @@ func TestWatchdogBase(t *testing.T) {
112112
t.Cleanup(func() { cleanupWatchdog(wd) })
113113

114114
wdDoneChan := make(chan bool, 1)
115+
testPreAction := func() error { return nil }
115116
go func() {
116-
wd.Start()
117+
wd.Start(testPreAction)
117118
wdDoneChan <- true
118119
}()
119120
waitProcessStart()
@@ -140,8 +141,9 @@ func TestWatchdogNotRestartable(t *testing.T) {
140141
t.Cleanup(func() { cleanupWatchdog(wd) })
141142

142143
wdDoneChan := make(chan bool, 1)
144+
testPreAction := func() error { return nil }
143145
go func() {
144-
wd.Start()
146+
wd.Start(testPreAction)
145147
wdDoneChan <- true
146148
}()
147149
waitProcessStart()

0 commit comments

Comments
 (0)