Skip to content

Commit

Permalink
fix(system-services): when the child process exits, roller should als…
Browse files Browse the repository at this point in the history
…o exit explicitly (#1124)
  • Loading branch information
artemijspavlovs authored Nov 22, 2024
1 parent dc0c86e commit 72119fb
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 20 deletions.
53 changes: 50 additions & 3 deletions cmd/da-light-client/start/start.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package start

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"

"github.com/pterm/pterm"
Expand Down Expand Up @@ -74,6 +76,7 @@ func Cmd() *cobra.Command {
}

fmt.Println(startDALCCmd.String())
done := make(chan error, 1)
if rollerData.KeyringBackend == consts.SupportedKeyringBackends.OS {
pswFileName, err := filesystem.GetOsKeyringPswFileName(consts.Executables.Celestia)
if err != nil {
Expand All @@ -93,11 +96,55 @@ func Cmd() *cobra.Command {
"Re-enter keyring passphrase": psw,
}

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// nolint: errcheck
go bash.ExecCmdFollow(startDALCCmd, pr)
go func() {
err := bash.ExecCmdFollow(
done,
ctx,
startDALCCmd,
pr, // No need for printOutput since we configured output above
)

done <- err
}()

select {
case err := <-done:
if err != nil {
pterm.Error.Println("da process returned an error: ", err)
os.Exit(1)
}
case <-ctx.Done():
pterm.Error.Println("context cancelled, terminating command")
return
}
} else {
// nolint: errcheck
go bash.ExecCmdFollow(startDALCCmd, nil)
ctx, cancel := context.WithCancel(cmd.Context())
defer cancel()

go func() {
err := bash.ExecCmdFollow(
done,
ctx,
startDALCCmd,
nil,
)

done <- err
}()

select {
case err := <-done:
if err != nil {
pterm.Error.Println("da process returned an error: ", err)
os.Exit(1)
}
case <-ctx.Done():
pterm.Error.Println("context cancelled, terminating command")
return
}
}
select {}
},
Expand Down
4 changes: 3 additions & 1 deletion cmd/eibc/scale/scale.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package scale

import (
"github.com/pterm/pterm"
"github.com/spf13/cobra"

"github.com/dymensionxyz/roller/utils/bash"
Expand All @@ -23,8 +24,9 @@ a good number to start with is 30 (default when initializing the eibc client)

c := eibcutils.GetScaleCmd(count)

err := bash.ExecCmdFollow(c, nil)
_, err := bash.ExecCommandWithStdout(c)
if err != nil {
pterm.Error.Println("failed to scale the number of fulfillers: ", err)
return
}
},
Expand Down
28 changes: 25 additions & 3 deletions cmd/eibc/start/start.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package start

import (
"context"
"os"
"path/filepath"

Expand Down Expand Up @@ -37,10 +38,31 @@ func Cmd() *cobra.Command {
return
}

done := make(chan error, 1)
c := eibcutils.GetStartCmd()
err = bash.ExecCmdFollow(c, nil)
if err != nil {
pterm.Error.Println("failed to start the eibc client:", err)

ctx, cancel := context.WithCancel(cmd.Context())
defer cancel()

go func() {
err := bash.ExecCmdFollow(
done,
ctx,
c,
nil, // No need for printOutput since we configured output above
)

done <- err
}()

select {
case err := <-done:
if err != nil {
pterm.Error.Println("eibc client process returned an error: ", err)
return
}
case <-ctx.Done():
pterm.Error.Println("context cancelled, terminating command")
return
}
},
Expand Down
46 changes: 40 additions & 6 deletions cmd/rollapp/start/start.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package start

import (
"context"
"fmt"
"os"
"os/exec"
Expand Down Expand Up @@ -95,6 +96,7 @@ Consider using 'services' if you want to run a 'systemd'(unix) or 'launchd'(mac)
go healthagent.Start(home, rollerLogger)
}

done := make(chan error, 1)
// nolint: errcheck
if rollappConfig.KeyringBackend == consts.SupportedKeyringBackends.OS {
pswFileName, err := filesystem.GetOsKeyringPswFileName(
Expand All @@ -117,12 +119,44 @@ Consider using 'services' if you want to run a 'systemd'(unix) or 'launchd'(mac)
"Re-enter keyring passphrase": psw,
}

go bash.ExecCmdFollow(
startRollappCmd,
pr,
)
ctx, cancel := context.WithCancel(cmd.Context())
defer cancel()
go func() {
err := bash.ExecCmdFollow(
done,
ctx,
startRollappCmd,
pr,
)

done <- err
}()
} else {
go bash.ExecCmdFollow(startRollappCmd, nil)
ctx, cancel := context.WithCancel(cmd.Context())
defer cancel()

go func() {
err := bash.ExecCmdFollow(
done,
ctx,
startRollappCmd,
nil, // No need for printOutput since we configured output above
)

done <- err
}()

select {
case err := <-done:
if err != nil {
pterm.Error.Println("rollapp's process returned an error: ", err)
os.Exit(1)
}
case <-ctx.Done():
pterm.Error.Println("context cancelled, terminating command")
return
}

}

select {}
Expand Down Expand Up @@ -245,7 +279,7 @@ func createPidFile(path string, cmd *exec.Cmd) error {
fmt.Println("Error creating file:", err)
return err
}
// nolint errcheck
// nolint: errcheck
defer file.Close()

pid := cmd.Process.Pid
Expand Down
51 changes: 44 additions & 7 deletions utils/bash/bash_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (
"io"
"os"
"os/exec"
"os/signal"
"strings"
"sync"
"syscall"
"time"

"github.com/pterm/pterm"
Expand Down Expand Up @@ -64,6 +66,7 @@ func RunCmdAsync(
for _, option := range options {
option(cmd)
}

if parseError == nil {
parseError = func(errMsg string) string {
return errMsg
Expand All @@ -75,6 +78,7 @@ func RunCmdAsync(
if cmd.Stderr != nil {
mw = io.MultiWriter(&stderr, cmd.Stderr)
}

cmd.Stderr = mw
err := cmd.Start()
if err != nil {
Expand Down Expand Up @@ -138,7 +142,15 @@ func ExecCmd(cmd *exec.Cmd, options ...CommandOption) error {
return nil
}

func ExecCmdFollow(cmd *exec.Cmd, promptResponses map[string]string) error {
func ExecCmdFollow(
doneChan chan<- error,
ctx context.Context,
cmd *exec.Cmd,
promptResponses map[string]string,
) error {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)

stdout, err := cmd.StdoutPipe()
if err != nil {
return err
Expand All @@ -157,6 +169,22 @@ func ExecCmdFollow(cmd *exec.Cmd, promptResponses map[string]string) error {
return err
}

// handle signals
go func() {
for {
select {
case sig := <-sigChan:
pterm.Info.Println("received signal: ", sig)
if cmd.Process != nil {
_ = cmd.Process.Signal(sig)
doneChan <- fmt.Errorf("received signal: %s", sig)
}
case <-ctx.Done():
_ = cmd.Process.Signal(syscall.SIGTERM)
}
}
}()

// Use a WaitGroup to wait for both stdout and stderr to be processed
var wg sync.WaitGroup
wg.Add(2)
Expand All @@ -183,23 +211,32 @@ func ExecCmdFollow(cmd *exec.Cmd, promptResponses map[string]string) error {
for scanner.Scan() {
fmt.Println(scanner.Text())
}

if err := scanner.Err(); err != nil {
errChan <- err
}
}()

// Wait for both stdout and stderr goroutines to finish
go func() {
wg.Wait()
close(errChan)
<-ctx.Done()
if cmd.Process != nil {
pterm.Info.Println("killing process: ", cmd.Process.Pid)
err = cmd.Process.Kill()
if err != nil {
pterm.Error.Println("failed to kill process: ", err)
}
}
}()

// Wait for the command to finish
if err := cmd.Wait(); err != nil {
err = cmd.Wait()
if err != nil {
return err
}

// Check if there were any errors in the goroutines
wg.Wait()
close(errChan)

// Check for any scanning errors
for err := range errChan {
if err != nil {
return err
Expand Down

0 comments on commit 72119fb

Please sign in to comment.