Skip to content

Commit fddd2d9

Browse files
committed
Fix race condition in Application and FasthttpService
1 parent 871dec7 commit fddd2d9

File tree

3 files changed

+35
-18
lines changed

3 files changed

+35
-18
lines changed

application.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ type ApplicationConfig struct {
1616
}
1717

1818
type Application struct {
19+
serviceState
1920
fasthttpService FasthttpService
2021
Configuration ApplicationConfig
21-
running bool
2222
done chan bool
2323
signals chan os.Signal
2424
}
@@ -33,6 +33,8 @@ func NewApplication(config ApplicationConfig, router Router) *Application {
3333
}
3434

3535
app.fasthttpService.Server.Handler = router.Handler()
36+
app.done = make(chan bool, 1)
37+
app.signals = make(chan os.Signal, 1)
3638

3739
return app
3840
}
@@ -57,17 +59,14 @@ func (app *Application) Start() error {
5759
return err
5860
}
5961

60-
app.done = make(chan bool, 1)
61-
app.signals = make(chan os.Signal, 1)
62-
6362
go func() {
6463
signal.Notify(app.signals, syscall.SIGINT, syscall.SIGTERM)
6564
if _, ok := <-app.signals; ok {
6665
app.Stop()
6766
}
6867
}()
6968

70-
app.running = true
69+
app.setRunning(true)
7170
if err := app.fasthttpService.Start(); err != nil {
7271
return err
7372
}
@@ -77,14 +76,14 @@ func (app *Application) Start() error {
7776
}
7877

7978
func (app *Application) Stop() error {
80-
if app.running {
79+
if app.isRunning() {
8180
defer func() {
8281
if app.Configuration.ServiceStarter != nil {
8382
app.Configuration.ServiceStarter.Stop(true)
8483
}
85-
close(app.signals)
86-
close(app.done)
87-
app.running = false
84+
signal.Stop(app.signals)
85+
app.done <- true
86+
app.setRunning(false)
8887
}()
8988
return app.fasthttpService.Stop()
9089
}

fasthttp_service.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type FasthttpServiceConfigurationTLS struct {
2323

2424
// FasthttpService implements the server for starting
2525
type FasthttpService struct {
26-
running bool
26+
serviceState
2727
Configuration FasthttpServiceConfiguration
2828
Server fasthttp.Server
2929
}
@@ -50,19 +50,16 @@ func (service *FasthttpService) ApplyConfiguration(configuration interface{}) er
5050

5151
// Restart returns an error due to fasthttp not being able to stop the service.
5252
func (service *FasthttpService) Restart() error {
53-
if service.running {
54-
err := service.Stop()
55-
if err != nil {
56-
return err
57-
}
53+
if err := service.Stop(); err != nil {
54+
return err
5855
}
5956
return service.Start()
6057
}
6158

6259
// Start ListenAndServe the server. This method is blocking because it uses
6360
// the fasthttp.ListenAndServe implementation.
6461
func (service *FasthttpService) Start() error {
65-
service.running = true
62+
service.setRunning(true)
6663

6764
if service.Configuration.TLS == nil {
6865
return service.Server.ListenAndServe(service.Configuration.Bind)
@@ -73,9 +70,10 @@ func (service *FasthttpService) Start() error {
7370

7471
// Stop closes the listener and waits the `Start` to stop.
7572
func (service *FasthttpService) Stop() error {
76-
if service.running {
77-
service.running = false
73+
if service.isRunning() {
74+
service.setRunning(false)
7875
return service.Server.Shutdown()
7976
}
77+
8078
return nil
8179
}

service_state.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package hermes
2+
3+
import "sync"
4+
5+
type serviceState struct {
6+
sync.RWMutex
7+
_running bool
8+
}
9+
10+
func (service *serviceState) isRunning() bool {
11+
service.RLock()
12+
defer service.RUnlock()
13+
return service._running
14+
}
15+
16+
func (service *serviceState) setRunning(v bool) {
17+
service.Lock()
18+
service._running = v
19+
service.Unlock()
20+
}

0 commit comments

Comments
 (0)