mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-08 22:31:04 +00:00
all: Get rid of fatal logging (#5537)
* cleanup Fatal in lib/config/config.go * cleanup Fatal in lib/config/folderconfiguration.go * cleanup Fatal in lib/model/model.go * cleanup Fatal in cmd/syncthing/monitor.go * cleanup Fatal in cmd/syncthing/main.go * cleanup Fatal in lib/api * remove Fatal methods from logger * lowercase in errors.Wrap * one less channel
This commit is contained in:
parent
7a40c42e8b
commit
d5ff2c41dc
@ -78,7 +78,8 @@ type apiService struct {
|
|||||||
stop chan struct{} // signals intentional stop
|
stop chan struct{} // signals intentional stop
|
||||||
configChanged chan struct{} // signals intentional listener close due to config change
|
configChanged chan struct{} // signals intentional listener close due to config change
|
||||||
started chan string // signals startup complete by sending the listener address, for testing only
|
started chan string // signals startup complete by sending the listener address, for testing only
|
||||||
startedOnce chan struct{} // the service has started successfully at least once
|
startedOnce chan struct{} // the service has started at least once
|
||||||
|
startupErr error
|
||||||
cpu rater
|
cpu rater
|
||||||
|
|
||||||
guiErrors logger.Recorder
|
guiErrors logger.Recorder
|
||||||
@ -174,6 +175,11 @@ func newAPIService(id protocol.DeviceID, cfg configIntf, httpsCertFile, httpsKey
|
|||||||
return service
|
return service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *apiService) WaitForStart() error {
|
||||||
|
<-s.startedOnce
|
||||||
|
return s.startupErr
|
||||||
|
}
|
||||||
|
|
||||||
func (s *apiService) getListener(guiCfg config.GUIConfiguration) (net.Listener, error) {
|
func (s *apiService) getListener(guiCfg config.GUIConfiguration) (net.Listener, error) {
|
||||||
cert, err := tls.LoadX509KeyPair(s.httpsCertFile, s.httpsKeyFile)
|
cert, err := tls.LoadX509KeyPair(s.httpsCertFile, s.httpsKeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -236,14 +242,15 @@ func (s *apiService) Serve() {
|
|||||||
// We let this be a loud user-visible warning as it may be the only
|
// We let this be a loud user-visible warning as it may be the only
|
||||||
// indication they get that the GUI won't be available.
|
// indication they get that the GUI won't be available.
|
||||||
l.Warnln("Starting API/GUI:", err)
|
l.Warnln("Starting API/GUI:", err)
|
||||||
return
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// This is during initialization. A failure here should be fatal
|
// This is during initialization. A failure here should be fatal
|
||||||
// as there will be no way for the user to communicate with us
|
// as there will be no way for the user to communicate with us
|
||||||
// otherwise anyway.
|
// otherwise anyway.
|
||||||
l.Fatalln("Starting API/GUI:", err)
|
s.startupErr = err
|
||||||
|
close(s.startedOnce)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if listener == nil {
|
if listener == nil {
|
||||||
@ -410,6 +417,19 @@ func (s *apiService) Serve() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Complete implements suture.IsCompletable, which signifies to the supervisor
|
||||||
|
// whether to stop restarting the service.
|
||||||
|
func (s *apiService) Complete() bool {
|
||||||
|
select {
|
||||||
|
case <-s.startedOnce:
|
||||||
|
return s.startupErr != nil
|
||||||
|
case <-s.stop:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (s *apiService) Stop() {
|
func (s *apiService) Stop() {
|
||||||
close(s.stop)
|
close(s.stop)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -48,6 +47,7 @@ import (
|
|||||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||||
"github.com/syncthing/syncthing/lib/upgrade"
|
"github.com/syncthing/syncthing/lib/upgrade"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/thejerf/suture"
|
"github.com/thejerf/suture"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -305,7 +305,8 @@ func main() {
|
|||||||
// to complain if they set -logfile explicitly, not if it's set to its
|
// to complain if they set -logfile explicitly, not if it's set to its
|
||||||
// default location
|
// default location
|
||||||
if options.noRestart && (options.logFile != "" && options.logFile != "-") {
|
if options.noRestart && (options.logFile != "" && options.logFile != "-") {
|
||||||
l.Fatalln("-logfile may not be used with -no-restart or STNORESTART")
|
l.Warnln("-logfile may not be used with -no-restart or STNORESTART")
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.hideConsole {
|
if options.hideConsole {
|
||||||
@ -318,11 +319,13 @@ func main() {
|
|||||||
var err error
|
var err error
|
||||||
options.confDir, err = filepath.Abs(options.confDir)
|
options.confDir, err = filepath.Abs(options.confDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln(err)
|
l.Warnln("Failed to make options path absolute:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := locations.SetBaseDir(locations.ConfigBaseDir, options.confDir); err != nil {
|
if err := locations.SetBaseDir(locations.ConfigBaseDir, options.confDir); err != nil {
|
||||||
l.Fatalln(err)
|
l.Warnln(err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,7 +362,8 @@ func main() {
|
|||||||
locations.Get(locations.KeyFile),
|
locations.Get(locations.KeyFile),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Error reading device ID:", err)
|
l.Warnln("Error reading device ID:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
|
|
||||||
myID = protocol.NewDeviceID(cert.Certificate[0])
|
myID = protocol.NewDeviceID(cert.Certificate[0])
|
||||||
@ -368,22 +372,32 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if options.browserOnly {
|
if options.browserOnly {
|
||||||
openGUI()
|
if err := openGUI(); err != nil {
|
||||||
|
l.Warnln("Failed to open web UI:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.generateDir != "" {
|
if options.generateDir != "" {
|
||||||
generate(options.generateDir)
|
if err := generate(options.generateDir); err != nil {
|
||||||
|
l.Warnln("Failed to generate config and keys:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that our home directory exists.
|
// Ensure that our home directory exists.
|
||||||
ensureDir(locations.GetBaseDir(locations.ConfigBaseDir), 0700)
|
if err := ensureDir(locations.GetBaseDir(locations.ConfigBaseDir), 0700); err != nil {
|
||||||
|
l.Warnln("Failure on home directory:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
|
}
|
||||||
|
|
||||||
if options.upgradeTo != "" {
|
if options.upgradeTo != "" {
|
||||||
err := upgrade.ToURL(options.upgradeTo)
|
err := upgrade.ToURL(options.upgradeTo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Upgrade:", err) // exits 1
|
l.Warnln("Error while Upgrading:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
l.Infoln("Upgraded from", options.upgradeTo)
|
l.Infoln("Upgraded from", options.upgradeTo)
|
||||||
return
|
return
|
||||||
@ -402,7 +416,8 @@ func main() {
|
|||||||
|
|
||||||
if options.resetDatabase {
|
if options.resetDatabase {
|
||||||
if err := resetDB(); err != nil {
|
if err := resetDB(); err != nil {
|
||||||
l.Fatalln("Resetting database:", err)
|
l.Warnln("Resetting database:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -414,23 +429,30 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func openGUI() {
|
func openGUI() error {
|
||||||
cfg, _ := loadOrDefaultConfig()
|
cfg, err := loadOrDefaultConfig()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if cfg.GUI().Enabled {
|
if cfg.GUI().Enabled {
|
||||||
if err := openURL(cfg.GUI().URL()); err != nil {
|
if err := openURL(cfg.GUI().URL()); err != nil {
|
||||||
l.Fatalln("Open URL:", err)
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
l.Warnln("Browser: GUI is currently disabled")
|
l.Warnln("Browser: GUI is currently disabled")
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generate(generateDir string) {
|
func generate(generateDir string) error {
|
||||||
dir, err := fs.ExpandTilde(generateDir)
|
dir, err := fs.ExpandTilde(generateDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("generate:", err)
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ensureDir(dir, 0700); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
ensureDir(dir, 0700)
|
|
||||||
|
|
||||||
certFile, keyFile := filepath.Join(dir, "cert.pem"), filepath.Join(dir, "key.pem")
|
certFile, keyFile := filepath.Join(dir, "cert.pem"), filepath.Join(dir, "key.pem")
|
||||||
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
||||||
@ -440,11 +462,11 @@ func generate(generateDir string) {
|
|||||||
} else {
|
} else {
|
||||||
cert, err = tlsutil.NewCertificate(certFile, keyFile, tlsDefaultCommonName)
|
cert, err = tlsutil.NewCertificate(certFile, keyFile, tlsDefaultCommonName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Create certificate:", err)
|
return errors.Wrap(err, "create certificate")
|
||||||
}
|
}
|
||||||
myID = protocol.NewDeviceID(cert.Certificate[0])
|
myID = protocol.NewDeviceID(cert.Certificate[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Load certificate:", err)
|
return errors.Wrap(err, "load certificate")
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
l.Infoln("Device ID:", protocol.NewDeviceID(cert.Certificate[0]))
|
l.Infoln("Device ID:", protocol.NewDeviceID(cert.Certificate[0]))
|
||||||
@ -454,13 +476,17 @@ func generate(generateDir string) {
|
|||||||
cfgFile := filepath.Join(dir, "config.xml")
|
cfgFile := filepath.Join(dir, "config.xml")
|
||||||
if _, err := os.Stat(cfgFile); err == nil {
|
if _, err := os.Stat(cfgFile); err == nil {
|
||||||
l.Warnln("Config exists; will not overwrite.")
|
l.Warnln("Config exists; will not overwrite.")
|
||||||
return
|
return nil
|
||||||
|
}
|
||||||
|
cfg, err := defaultConfig(cfgFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
var cfg = defaultConfig(cfgFile)
|
|
||||||
err = cfg.Save()
|
err = cfg.Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Warnln("Failed to save config", err)
|
return errors.Wrap(err, "save config")
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func debugFacilities() string {
|
func debugFacilities() string {
|
||||||
@ -490,7 +516,8 @@ func checkUpgrade() upgrade.Release {
|
|||||||
opts := cfg.Options()
|
opts := cfg.Options()
|
||||||
release, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases)
|
release, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Upgrade:", err)
|
l.Warnln("Upgrade:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if upgrade.CompareVersions(release.Tag, build.Version) <= 0 {
|
if upgrade.CompareVersions(release.Tag, build.Version) <= 0 {
|
||||||
@ -509,14 +536,16 @@ func performUpgrade(release upgrade.Release) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
err = upgrade.To(release)
|
err = upgrade.To(release)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Upgrade:", err)
|
l.Warnln("Upgrade:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
l.Infof("Upgraded to %q", release.Tag)
|
l.Infof("Upgraded to %q", release.Tag)
|
||||||
} else {
|
} else {
|
||||||
l.Infoln("Attempting upgrade through running Syncthing...")
|
l.Infoln("Attempting upgrade through running Syncthing...")
|
||||||
err = upgradeViaRest()
|
err = upgradeViaRest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Upgrade:", err)
|
l.Warnln("Upgrade:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
l.Infoln("Syncthing upgrading")
|
l.Infoln("Syncthing upgrading")
|
||||||
os.Exit(exitUpgrading)
|
os.Exit(exitUpgrading)
|
||||||
@ -615,7 +644,8 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
tlsDefaultCommonName,
|
tlsDefaultCommonName,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln(err)
|
l.Infoln("Failed to generate certificate:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,10 +667,15 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
"myID": myID.String(),
|
"myID": myID.String(),
|
||||||
})
|
})
|
||||||
|
|
||||||
cfg := loadConfigAtStartup()
|
cfg, err := loadConfigAtStartup()
|
||||||
|
if err != nil {
|
||||||
|
l.Warnln("Failed to initialize config:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
|
}
|
||||||
|
|
||||||
if err := checkShortIDs(cfg); err != nil {
|
if err := checkShortIDs(cfg); err != nil {
|
||||||
l.Fatalln("Short device IDs are in conflict. Unlucky!\n Regenerate the device ID of one of the following:\n ", err)
|
l.Warnln("Short device IDs are in conflict. Unlucky!\n Regenerate the device ID of one of the following:\n ", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(runtimeOptions.profiler) > 0 {
|
if len(runtimeOptions.profiler) > 0 {
|
||||||
@ -649,7 +684,8 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
runtime.SetBlockProfileRate(1)
|
runtime.SetBlockProfileRate(1)
|
||||||
err := http.ListenAndServe(runtimeOptions.profiler, nil)
|
err := http.ListenAndServe(runtimeOptions.profiler, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln(err)
|
l.Warnln(err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@ -660,10 +696,12 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
dbFile := locations.Get(locations.Database)
|
dbFile := locations.Get(locations.Database)
|
||||||
ldb, err := db.Open(dbFile)
|
ldb, err := db.Open(dbFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Error opening database:", err)
|
l.Warnln("Error opening database:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
if err := db.UpdateSchema(ldb); err != nil {
|
if err := db.UpdateSchema(ldb); err != nil {
|
||||||
l.Fatalln("Database schema:", err)
|
l.Warnln("Database schema:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if runtimeOptions.resetDeltaIdxs {
|
if runtimeOptions.resetDeltaIdxs {
|
||||||
@ -799,10 +837,12 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
if runtimeOptions.cpuProfile {
|
if runtimeOptions.cpuProfile {
|
||||||
f, err := os.Create(fmt.Sprintf("cpu-%d.pprof", os.Getpid()))
|
f, err := os.Create(fmt.Sprintf("cpu-%d.pprof", os.Getpid()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Creating profile:", err)
|
l.Warnln("Creating profile:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
if err := pprof.StartCPUProfile(f); err != nil {
|
if err := pprof.StartCPUProfile(f); err != nil {
|
||||||
l.Fatalln("Starting profile:", err)
|
l.Warnln("Starting profile:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -921,33 +961,39 @@ func loadOrDefaultConfig() (*config.Wrapper, error) {
|
|||||||
cfg, err := config.Load(cfgFile, myID)
|
cfg, err := config.Load(cfgFile, myID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cfg = defaultConfig(cfgFile)
|
cfg, err = defaultConfig(cfgFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg, err
|
return cfg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfigAtStartup() *config.Wrapper {
|
func loadConfigAtStartup() (*config.Wrapper, error) {
|
||||||
cfgFile := locations.Get(locations.ConfigFile)
|
cfgFile := locations.Get(locations.ConfigFile)
|
||||||
cfg, err := config.Load(cfgFile, myID)
|
cfg, err := config.Load(cfgFile, myID)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
cfg = defaultConfig(cfgFile)
|
cfg, err = defaultConfig(cfgFile)
|
||||||
cfg.Save()
|
if err != nil {
|
||||||
l.Infof("Default config saved. Edit %s to taste or use the GUI\n", cfg.ConfigPath())
|
return nil, errors.Wrap(err, "failed to generate default config")
|
||||||
|
}
|
||||||
|
err = cfg.Save()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to save default config")
|
||||||
|
}
|
||||||
|
l.Infof("Default config saved. Edit %s to taste (with Syncthing stopped) or use the GUI", cfg.ConfigPath())
|
||||||
} else if err == io.EOF {
|
} else if err == io.EOF {
|
||||||
l.Fatalln("Failed to load config: unexpected end of file. Truncated or empty configuration?")
|
return nil, errors.New("Failed to load config: unexpected end of file. Truncated or empty configuration?")
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
l.Fatalln("Failed to load config:", err)
|
return nil, errors.Wrap(err, "failed to load config")
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.RawCopy().OriginalVersion != config.CurrentVersion {
|
if cfg.RawCopy().OriginalVersion != config.CurrentVersion {
|
||||||
err = archiveAndSaveConfig(cfg)
|
err = archiveAndSaveConfig(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Config archive:", err)
|
return nil, errors.Wrap(err, "config archive")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func archiveAndSaveConfig(cfg *config.Wrapper) error {
|
func archiveAndSaveConfig(cfg *config.Wrapper) error {
|
||||||
@ -999,7 +1045,8 @@ func startAuditing(mainService *suture.Supervisor, auditFile string) {
|
|||||||
}
|
}
|
||||||
fd, err = os.OpenFile(auditFile, auditFlags, 0600)
|
fd, err = os.OpenFile(auditFile, auditFlags, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("Audit:", err)
|
l.Warnln("Audit:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
auditDest = auditFile
|
auditDest = auditFile
|
||||||
}
|
}
|
||||||
@ -1032,36 +1079,43 @@ func setupGUI(mainService *suture.Supervisor, cfg *config.Wrapper, m *model.Mode
|
|||||||
cfg.Subscribe(api)
|
cfg.Subscribe(api)
|
||||||
mainService.Add(api)
|
mainService.Add(api)
|
||||||
|
|
||||||
|
if err := api.WaitForStart(); err != nil {
|
||||||
|
l.Warnln("Failed starting API:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
|
}
|
||||||
|
|
||||||
if cfg.Options().StartBrowser && !runtimeOptions.noBrowser && !runtimeOptions.stRestarting {
|
if cfg.Options().StartBrowser && !runtimeOptions.noBrowser && !runtimeOptions.stRestarting {
|
||||||
// Can potentially block if the utility we are invoking doesn't
|
// Can potentially block if the utility we are invoking doesn't
|
||||||
// fork, and just execs, hence keep it in its own routine.
|
// fork, and just execs, hence keep it in its own routine.
|
||||||
<-api.startedOnce
|
|
||||||
go func() { _ = openURL(guiCfg.URL()) }()
|
go func() { _ = openURL(guiCfg.URL()) }()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultConfig(cfgFile string) *config.Wrapper {
|
func defaultConfig(cfgFile string) (*config.Wrapper, error) {
|
||||||
newCfg := config.NewWithFreePorts(myID)
|
newCfg, err := config.NewWithFreePorts(myID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if noDefaultFolder {
|
if noDefaultFolder {
|
||||||
l.Infoln("We will skip creation of a default folder on first start since the proper envvar is set")
|
l.Infoln("We will skip creation of a default folder on first start since the proper envvar is set")
|
||||||
return config.Wrap(cfgFile, newCfg)
|
return config.Wrap(cfgFile, newCfg), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
newCfg.Folders = append(newCfg.Folders, config.NewFolderConfiguration(myID, "default", "Default Folder", fs.FilesystemTypeBasic, locations.Get(locations.DefFolder)))
|
newCfg.Folders = append(newCfg.Folders, config.NewFolderConfiguration(myID, "default", "Default Folder", fs.FilesystemTypeBasic, locations.Get(locations.DefFolder)))
|
||||||
l.Infoln("Default folder created and/or linked to new config")
|
l.Infoln("Default folder created and/or linked to new config")
|
||||||
return config.Wrap(cfgFile, newCfg)
|
return config.Wrap(cfgFile, newCfg), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resetDB() error {
|
func resetDB() error {
|
||||||
return os.RemoveAll(locations.Get(locations.Database))
|
return os.RemoveAll(locations.Get(locations.Database))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureDir(dir string, mode fs.FileMode) {
|
func ensureDir(dir string, mode fs.FileMode) error {
|
||||||
fs := fs.NewFilesystem(fs.FilesystemTypeBasic, dir)
|
fs := fs.NewFilesystem(fs.FilesystemTypeBasic, dir)
|
||||||
err := fs.MkdirAll(".", mode)
|
err := fs.MkdirAll(".", mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if fi, err := fs.Stat("."); err == nil {
|
if fi, err := fs.Stat("."); err == nil {
|
||||||
@ -1077,6 +1131,7 @@ func ensureDir(dir string, mode fs.FileMode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func standbyMonitor() {
|
func standbyMonitor() {
|
||||||
@ -1232,6 +1287,7 @@ func setPauseState(cfg *config.Wrapper, paused bool) {
|
|||||||
raw.Folders[i].Paused = paused
|
raw.Folders[i].Paused = paused
|
||||||
}
|
}
|
||||||
if _, err := cfg.Replace(raw); err != nil {
|
if _, err := cfg.Replace(raw); err != nil {
|
||||||
l.Fatalln("Cannot adjust paused state:", err)
|
l.Warnln("Cannot adjust paused state:", err)
|
||||||
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,18 +85,18 @@ func monitorMain(runtimeOptions RuntimeOptions) {
|
|||||||
|
|
||||||
stderr, err := cmd.StderrPipe()
|
stderr, err := cmd.StderrPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("stderr:", err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("stdout:", err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Infoln("Starting syncthing")
|
l.Infoln("Starting syncthing")
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stdoutMut.Lock()
|
stdoutMut.Lock()
|
||||||
|
@ -84,18 +84,18 @@ func New(myID protocol.DeviceID) Configuration {
|
|||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWithFreePorts(myID protocol.DeviceID) Configuration {
|
func NewWithFreePorts(myID protocol.DeviceID) (Configuration, error) {
|
||||||
cfg := New(myID)
|
cfg := New(myID)
|
||||||
|
|
||||||
port, err := getFreePort("127.0.0.1", DefaultGUIPort)
|
port, err := getFreePort("127.0.0.1", DefaultGUIPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("get free port (GUI):", err)
|
return Configuration{}, fmt.Errorf("get free port (GUI): %v", err)
|
||||||
}
|
}
|
||||||
cfg.GUI.RawAddress = fmt.Sprintf("127.0.0.1:%d", port)
|
cfg.GUI.RawAddress = fmt.Sprintf("127.0.0.1:%d", port)
|
||||||
|
|
||||||
port, err = getFreePort("0.0.0.0", DefaultTCPPort)
|
port, err = getFreePort("0.0.0.0", DefaultTCPPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Fatalln("get free port (BEP):", err)
|
return Configuration{}, fmt.Errorf("get free port (BEP): %v", err)
|
||||||
}
|
}
|
||||||
if port == DefaultTCPPort {
|
if port == DefaultTCPPort {
|
||||||
cfg.Options.ListenAddresses = []string{"default"}
|
cfg.Options.ListenAddresses = []string{"default"}
|
||||||
@ -106,7 +106,7 @@ func NewWithFreePorts(myID protocol.DeviceID) Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadXML(r io.Reader, myID protocol.DeviceID) (Configuration, error) {
|
func ReadXML(r io.Reader, myID protocol.DeviceID) (Configuration, error) {
|
||||||
|
@ -106,7 +106,7 @@ func (f FolderConfiguration) Versioner() versioner.Versioner {
|
|||||||
}
|
}
|
||||||
versionerFactory, ok := versioner.Factories[f.Versioning.Type]
|
versionerFactory, ok := versioner.Factories[f.Versioning.Type]
|
||||||
if !ok {
|
if !ok {
|
||||||
l.Fatalf("Requested versioning type %q that does not exist", f.Versioning.Type)
|
panic(fmt.Sprintf("Requested versioning type %q that does not exist", f.Versioning.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
return versionerFactory(f.ID, f.Filesystem(), f.Versioning.Params)
|
return versionerFactory(f.ID, f.Filesystem(), f.Versioning.Params)
|
||||||
|
@ -25,7 +25,6 @@ const (
|
|||||||
LevelVerbose
|
LevelVerbose
|
||||||
LevelInfo
|
LevelInfo
|
||||||
LevelWarn
|
LevelWarn
|
||||||
LevelFatal
|
|
||||||
NumLevels
|
NumLevels
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -49,8 +48,6 @@ type Logger interface {
|
|||||||
Infof(format string, vals ...interface{})
|
Infof(format string, vals ...interface{})
|
||||||
Warnln(vals ...interface{})
|
Warnln(vals ...interface{})
|
||||||
Warnf(format string, vals ...interface{})
|
Warnf(format string, vals ...interface{})
|
||||||
Fatalln(vals ...interface{})
|
|
||||||
Fatalf(format string, vals ...interface{})
|
|
||||||
ShouldDebug(facility string) bool
|
ShouldDebug(facility string) bool
|
||||||
SetDebug(facility string, enabled bool)
|
SetDebug(facility string, enabled bool)
|
||||||
Facilities() map[string]string
|
Facilities() map[string]string
|
||||||
@ -190,28 +187,6 @@ func (l *logger) Warnf(format string, vals ...interface{}) {
|
|||||||
l.callHandlers(LevelWarn, s)
|
l.callHandlers(LevelWarn, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatalln logs a line with a FATAL prefix and exits the process with exit
|
|
||||||
// code 1.
|
|
||||||
func (l *logger) Fatalln(vals ...interface{}) {
|
|
||||||
s := fmt.Sprintln(vals...)
|
|
||||||
l.mut.Lock()
|
|
||||||
defer l.mut.Unlock()
|
|
||||||
l.logger.Output(2, "FATAL: "+s)
|
|
||||||
l.callHandlers(LevelFatal, s)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fatalf logs a formatted line with a FATAL prefix and exits the process with
|
|
||||||
// exit code 1.
|
|
||||||
func (l *logger) Fatalf(format string, vals ...interface{}) {
|
|
||||||
s := fmt.Sprintf(format, vals...)
|
|
||||||
l.mut.Lock()
|
|
||||||
defer l.mut.Unlock()
|
|
||||||
l.logger.Output(2, "FATAL: "+s)
|
|
||||||
l.callHandlers(LevelFatal, s)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShouldDebug returns true if the given facility has debugging enabled.
|
// ShouldDebug returns true if the given facility has debugging enabled.
|
||||||
func (l *logger) ShouldDebug(facility string) bool {
|
func (l *logger) ShouldDebug(facility string) bool {
|
||||||
l.mut.Lock()
|
l.mut.Lock()
|
||||||
|
@ -923,7 +923,7 @@ func (m *Model) handleIndex(deviceID protocol.DeviceID, folder string, fs []prot
|
|||||||
m.fmut.RUnlock()
|
m.fmut.RUnlock()
|
||||||
|
|
||||||
if !existing {
|
if !existing {
|
||||||
l.Fatalf("%v for nonexistent folder %q", op, folder)
|
panic(fmt.Sprintf("%v for nonexistent folder %q", op, folder))
|
||||||
}
|
}
|
||||||
|
|
||||||
if running {
|
if running {
|
||||||
@ -931,7 +931,7 @@ func (m *Model) handleIndex(deviceID protocol.DeviceID, folder string, fs []prot
|
|||||||
} else if update {
|
} else if update {
|
||||||
// Runner may legitimately not be set if this is the "cleanup" Index
|
// Runner may legitimately not be set if this is the "cleanup" Index
|
||||||
// message at startup.
|
// message at startup.
|
||||||
l.Fatalf("%v for not running folder %q", op, folder)
|
panic(fmt.Sprintf("%v for not running folder %q", op, folder))
|
||||||
}
|
}
|
||||||
|
|
||||||
m.pmut.RLock()
|
m.pmut.RLock()
|
||||||
|
Loading…
Reference in New Issue
Block a user