Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 40 additions & 40 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -1444,49 +1444,49 @@ func (*disableLogger) Printf(string, ...any) {
}

func (app *App) init() *App {
// lock application
app.mutex.Lock()

// Initialize Services when needed,
// panics if there is an error starting them.
app.initServices()
func() {
// lock application
app.mutex.Lock()
defer app.mutex.Unlock()

// Initialize Services when needed,
// panics if there is an error starting them.
app.initServices()

// Only load templates if a view engine is specified
if app.config.Views != nil {
if err := app.config.Views.Load(); err != nil {
log.Warnf("failed to load views: %v", err)
}
}

// Only load templates if a view engine is specified
if app.config.Views != nil {
if err := app.config.Views.Load(); err != nil {
log.Warnf("failed to load views: %v", err)
// create fasthttp server
app.server = &fasthttp.Server{
Logger: &disableLogger{},
LogAllErrors: false,
ErrorHandler: app.serverErrorHandler,
}
}

// create fasthttp server
app.server = &fasthttp.Server{
Logger: &disableLogger{},
LogAllErrors: false,
ErrorHandler: app.serverErrorHandler,
}

// fasthttp server settings
app.server.Handler = app.selectRequestHandler()
app.server.Name = app.config.ServerHeader
app.server.Concurrency = app.config.Concurrency
app.server.NoDefaultDate = app.config.DisableDefaultDate
app.server.NoDefaultContentType = app.config.DisableDefaultContentType
app.server.DisableHeaderNamesNormalizing = app.config.DisableHeaderNormalizing
app.server.DisableKeepalive = app.config.DisableKeepalive
app.server.MaxRequestBodySize = app.config.BodyLimit
app.server.NoDefaultServerHeader = app.config.ServerHeader == ""
app.server.ReadTimeout = app.config.ReadTimeout
app.server.WriteTimeout = app.config.WriteTimeout
app.server.IdleTimeout = app.config.IdleTimeout
app.server.ReadBufferSize = app.config.ReadBufferSize
app.server.WriteBufferSize = app.config.WriteBufferSize
app.server.GetOnly = app.config.GETOnly
app.server.ReduceMemoryUsage = app.config.ReduceMemoryUsage
app.server.StreamRequestBody = app.config.StreamRequestBody
app.server.DisablePreParseMultipartForm = app.config.DisablePreParseMultipartForm

// unlock application
app.mutex.Unlock()
// fasthttp server settings
app.server.Handler = app.selectRequestHandler()
app.server.Name = app.config.ServerHeader
app.server.Concurrency = app.config.Concurrency
app.server.NoDefaultDate = app.config.DisableDefaultDate
app.server.NoDefaultContentType = app.config.DisableDefaultContentType
app.server.DisableHeaderNamesNormalizing = app.config.DisableHeaderNormalizing
app.server.DisableKeepalive = app.config.DisableKeepalive
app.server.MaxRequestBodySize = app.config.BodyLimit
app.server.NoDefaultServerHeader = app.config.ServerHeader == ""
app.server.ReadTimeout = app.config.ReadTimeout
app.server.WriteTimeout = app.config.WriteTimeout
app.server.IdleTimeout = app.config.IdleTimeout
app.server.ReadBufferSize = app.config.ReadBufferSize
app.server.WriteBufferSize = app.config.WriteBufferSize
app.server.GetOnly = app.config.GETOnly
app.server.ReduceMemoryUsage = app.config.ReduceMemoryUsage
app.server.StreamRequestBody = app.config.StreamRequestBody
app.server.DisablePreParseMultipartForm = app.config.DisablePreParseMultipartForm
}()

// Register the Services shutdown handler once the app is initialized and unlocked.
app.Hooks().OnPostShutdown(func(_ error) error {
Expand Down
41 changes: 41 additions & 0 deletions app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2222,6 +2222,47 @@ func Test_App_ReloadViews_PanicUnlocksRender(t *testing.T) {
}
}

func Test_App_InitPanicUnlocksRouteRegistration(t *testing.T) {
t.Parallel()

view := &panicLoadView{}
app := New(Config{Views: view})

type initResult struct {
recovered any
}

initDone := make(chan initResult, 1)
go func() {
result := initResult{}
defer func() {
result.recovered = recover()
initDone <- result
}()

app.init()
}()

select {
case result := <-initDone:
require.Equal(t, "panic load", result.recovered)
case <-time.After(time.Second):
t.Fatal("init panic was not recovered")
}

registerDone := make(chan struct{}, 1)
go func() {
app.Get("/after-panic", func(Ctx) error { return nil })
registerDone <- struct{}{}
}()

select {
case <-registerDone:
case <-time.After(time.Second):
t.Fatal("route registration deadlocked after init panic")
}
}

func Test_App_RenderPanicUnlocksReloadViews(t *testing.T) {
t.Parallel()

Expand Down
Loading