Skip to content

Commit

Permalink
Fix race condition in Application and FasthttpService
Browse files Browse the repository at this point in the history
  • Loading branch information
felipemfp committed Aug 14, 2019
1 parent 871dec7 commit fddd2d9
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 18 deletions.
17 changes: 8 additions & 9 deletions application.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ type ApplicationConfig struct {
}

type Application struct {
serviceState
fasthttpService FasthttpService
Configuration ApplicationConfig
running bool
done chan bool
signals chan os.Signal
}
Expand All @@ -33,6 +33,8 @@ func NewApplication(config ApplicationConfig, router Router) *Application {
}

app.fasthttpService.Server.Handler = router.Handler()
app.done = make(chan bool, 1)
app.signals = make(chan os.Signal, 1)

return app
}
Expand All @@ -57,17 +59,14 @@ func (app *Application) Start() error {
return err
}

app.done = make(chan bool, 1)
app.signals = make(chan os.Signal, 1)

go func() {
signal.Notify(app.signals, syscall.SIGINT, syscall.SIGTERM)
if _, ok := <-app.signals; ok {
app.Stop()
}
}()

app.running = true
app.setRunning(true)
if err := app.fasthttpService.Start(); err != nil {
return err
}
Expand All @@ -77,14 +76,14 @@ func (app *Application) Start() error {
}

func (app *Application) Stop() error {
if app.running {
if app.isRunning() {
defer func() {
if app.Configuration.ServiceStarter != nil {
app.Configuration.ServiceStarter.Stop(true)
}
close(app.signals)
close(app.done)
app.running = false
signal.Stop(app.signals)
app.done <- true
app.setRunning(false)
}()
return app.fasthttpService.Stop()
}
Expand Down
16 changes: 7 additions & 9 deletions fasthttp_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type FasthttpServiceConfigurationTLS struct {

// FasthttpService implements the server for starting
type FasthttpService struct {
running bool
serviceState
Configuration FasthttpServiceConfiguration
Server fasthttp.Server
}
Expand All @@ -50,19 +50,16 @@ func (service *FasthttpService) ApplyConfiguration(configuration interface{}) er

// Restart returns an error due to fasthttp not being able to stop the service.
func (service *FasthttpService) Restart() error {
if service.running {
err := service.Stop()
if err != nil {
return err
}
if err := service.Stop(); err != nil {
return err
}
return service.Start()
}

// Start ListenAndServe the server. This method is blocking because it uses
// the fasthttp.ListenAndServe implementation.
func (service *FasthttpService) Start() error {
service.running = true
service.setRunning(true)

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

// Stop closes the listener and waits the `Start` to stop.
func (service *FasthttpService) Stop() error {
if service.running {
service.running = false
if service.isRunning() {
service.setRunning(false)
return service.Server.Shutdown()
}

return nil
}
20 changes: 20 additions & 0 deletions service_state.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package hermes

import "sync"

type serviceState struct {
sync.RWMutex
_running bool
}

func (service *serviceState) isRunning() bool {
service.RLock()
defer service.RUnlock()
return service._running
}

func (service *serviceState) setRunning(v bool) {
service.Lock()
service._running = v
service.Unlock()
}

0 comments on commit fddd2d9

Please sign in to comment.