Files
mostlymatter/cmd/mattermost/commands/server.go
Agniva De Sarker d48eec6727 MM-27887: set traceback to crash from code (#15274)
Unless we set traceback level to crash, goroutines from all threads aren't printed.
See: https://github.com/golang/go/issues/13161.

This is important because SIGQUIT traces will miss on goroutines.

https://mattermost.atlassian.net/browse/MM-27887
2020-08-17 22:08:25 +05:30

135 строки
3.5 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package commands
import (
"net"
"os"
"os/signal"
"runtime/debug"
"syscall"
"github.com/mattermost/mattermost-server/v5/api4"
"github.com/mattermost/mattermost-server/v5/app"
"github.com/mattermost/mattermost-server/v5/config"
"github.com/mattermost/mattermost-server/v5/manualtesting"
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/mattermost-server/v5/utils"
"github.com/mattermost/mattermost-server/v5/web"
"github.com/mattermost/mattermost-server/v5/wsapi"
"github.com/mattermost/viper"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
var serverCmd = &cobra.Command{
Use: "server",
Short: "Run the Mattermost server",
RunE: serverCmdF,
SilenceUsage: true,
}
func init() {
RootCmd.AddCommand(serverCmd)
RootCmd.RunE = serverCmdF
}
func serverCmdF(command *cobra.Command, args []string) error {
configDSN := viper.GetString("config")
disableConfigWatch, _ := command.Flags().GetBool("disableconfigwatch")
usedPlatform, _ := command.Flags().GetBool("platform")
interruptChan := make(chan os.Signal, 1)
if err := utils.TranslationsPreInit(); err != nil {
return errors.Wrapf(err, "unable to load Mattermost translation files")
}
configStore, err := config.NewStore(configDSN, !disableConfigWatch)
if err != nil {
return errors.Wrap(err, "failed to load configuration")
}
return runServer(configStore, disableConfigWatch, usedPlatform, interruptChan)
}
func runServer(configStore config.Store, disableConfigWatch bool, usedPlatform bool, interruptChan chan os.Signal) error {
// Setting the highest traceback level from the code.
// This is done to print goroutines from all threads (see golang.org/issue/13161)
// and also preserve a crash dump for later investigation.
debug.SetTraceback("crash")
options := []app.Option{
app.ConfigStore(configStore),
app.RunJobs,
app.JoinCluster,
app.StartSearchEngine,
app.StartMetrics,
}
server, err := app.NewServer(options...)
if err != nil {
mlog.Critical(err.Error())
return err
}
defer server.Shutdown()
if usedPlatform {
mlog.Error("The platform binary has been deprecated, please switch to using the mattermost binary.")
}
api := api4.Init(server, server.AppOptions, server.Router)
wsapi.Init(server)
web.New(server, server.AppOptions, server.Router)
api4.InitLocal(server, server.AppOptions, server.LocalRouter)
serverErr := server.Start()
if serverErr != nil {
mlog.Critical(serverErr.Error())
return serverErr
}
// If we allow testing then listen for manual testing URL hits
if *server.Config().ServiceSettings.EnableTesting {
manualtesting.Init(api)
}
notifyReady()
// wait for kill signal before attempting to gracefully shutdown
// the running service
signal.Notify(interruptChan, syscall.SIGINT, syscall.SIGTERM)
<-interruptChan
return nil
}
func notifyReady() {
// If the environment vars provide a systemd notification socket,
// notify systemd that the server is ready.
systemdSocket := os.Getenv("NOTIFY_SOCKET")
if systemdSocket != "" {
mlog.Info("Sending systemd READY notification.")
err := sendSystemdReadyNotification(systemdSocket)
if err != nil {
mlog.Error(err.Error())
}
}
}
func sendSystemdReadyNotification(socketPath string) error {
msg := "READY=1"
addr := &net.UnixAddr{
Name: socketPath,
Net: "unixgram",
}
conn, err := net.DialUnix(addr.Net, nil, addr)
if err != nil {
return err
}
defer conn.Close()
_, err = conn.Write([]byte(msg))
return err
}