diff --git a/tools/cosmovisor/process_test.go b/tools/cosmovisor/process_test.go index e019c8b98f..988bcf0a80 100644 --- a/tools/cosmovisor/process_test.go +++ b/tools/cosmovisor/process_test.go @@ -25,7 +25,7 @@ import ( func TestLaunchProcess(t *testing.T) { // binaries from testdata/validate directory home := copyTestData(t, "validate") - cfg := &cosmovisor.Config{Home: home, Name: "dummyd", PollInterval: 20, UnsafeSkipBackup: true} + cfg := &cosmovisor.Config{Home: home, Name: "dummyd", PollInterval: 15, UnsafeSkipBackup: true} logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output @@ -145,7 +145,7 @@ func TestLaunchProcessWithRestartDelay(t *testing.T) { func TestPlanShutdownGrace(t *testing.T) { // binaries from testdata/validate directory home := copyTestData(t, "dontdie") - cfg := &cosmovisor.Config{Home: home, Name: "dummyd", PollInterval: 20, UnsafeSkipBackup: true, ShutdownGrace: 2 * time.Second} + cfg := &cosmovisor.Config{Home: home, Name: "dummyd", PollInterval: 15, UnsafeSkipBackup: true, ShutdownGrace: 2 * time.Second} logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output diff --git a/tools/cosmovisor/scanner.go b/tools/cosmovisor/scanner.go index a5bfdf2cc0..6b46f85baf 100644 --- a/tools/cosmovisor/scanner.go +++ b/tools/cosmovisor/scanner.go @@ -16,7 +16,7 @@ import ( ) type fileWatcher struct { - deamonHome string + daemonHome string filename string // full path to a watched file interval time.Duration @@ -53,7 +53,7 @@ func newUpgradeFileWatcher(cfg *Config) (*fileWatcher, error) { } return &fileWatcher{ - deamonHome: cfg.Home, + daemonHome: cfg.Home, currentBin: bin, filename: filenameAbs, interval: cfg.PollInterval, @@ -109,7 +109,32 @@ func (fw *fileWatcher) CheckUpdate(currentUpgrade upgradetypes.Plan) bool { stat, err := os.Stat(fw.filename) if err != nil { - // file doesn't exists + if os.IsNotExist(err) { + return false + } else { + panic(fmt.Errorf("failed to stat upgrade info file: %w", err)) + } + } + + // check https://github.com/cosmos/cosmos-sdk/issues/21086 + // If new file is still empty, wait a small amount of time for write to complete + if stat.Size() == 0 { + for range 10 { + time.Sleep(2 * time.Millisecond) + stat, err = os.Stat(fw.filename) + if err != nil { + if os.IsNotExist(err) { + return false + } else { + panic(fmt.Errorf("failed to stat upgrade info file: %w", err)) + } + } + if stat.Size() == 0 { + break + } + } + } + if stat.Size() == 0 { return false } @@ -118,13 +143,6 @@ func (fw *fileWatcher) CheckUpdate(currentUpgrade upgradetypes.Plan) bool { return false } - // if fw.lastModTime.IsZero() { // check https://github.com/cosmos/cosmos-sdk/issues/21086 - // // first initialization or daemon restart while upgrading-info.json exists. - // // it could be that it was just created and not fully written to disk. - // // wait tiniest bit of time to allow the file to be fully written. - // time.Sleep(2 * time.Millisecond) - // } - info, err := parseUpgradeInfoFile(fw.filename, fw.disableRecase) if err != nil { panic(fmt.Errorf("failed to parse upgrade info file: %w", err)) @@ -167,7 +185,7 @@ func (fw *fileWatcher) checkHeight() (int64, error) { return 0, nil } - result, err := exec.Command(fw.currentBin, "status", "--home", fw.deamonHome).CombinedOutput() //nolint:gosec // we want to execute the status command + result, err := exec.Command(fw.currentBin, "status", "--home", fw.daemonHome).CombinedOutput() //nolint:gosec // we want to execute the status command if err != nil { return 0, err } diff --git a/tools/cosmovisor/testdata/dontdie/cosmovisor/genesis/bin/dummyd b/tools/cosmovisor/testdata/dontdie/cosmovisor/genesis/bin/dummyd index 49e60a1e20..8694ec8e8e 100755 --- a/tools/cosmovisor/testdata/dontdie/cosmovisor/genesis/bin/dummyd +++ b/tools/cosmovisor/testdata/dontdie/cosmovisor/genesis/bin/dummyd @@ -11,7 +11,10 @@ sleep 1 test -z $4 && exit 1001 echo 'UPGRADE "Chain2" NEEDED at height: 49: {}' echo '{"name":"Chain2","height":49,"info":""}' > $4 +# Shutdown grace test waits 2 seconds for flush +# Flush within 1 second sleep 1 echo 'Flushed' -sleep 1 +# Now chain is halted for shutdown grace test. +sleep 2 echo Did not kill in time. Never should be printed!!!