@@ -19,6 +19,7 @@ import (
19
19
"github.com/pyroscope-io/pyroscope/pkg/agent/spy"
20
20
"github.com/pyroscope-io/pyroscope/pkg/agent/upstream/remote"
21
21
"github.com/pyroscope-io/pyroscope/pkg/config"
22
+ "github.com/pyroscope-io/pyroscope/pkg/util/atexit"
22
23
"github.com/sirupsen/logrus"
23
24
)
24
25
@@ -32,7 +33,7 @@ func Cli(cfg *config.Config, args []string) error {
32
33
baseName := path .Base (args [0 ])
33
34
spyName = spy .ResolveAutoName (baseName )
34
35
if spyName == "" {
35
- supportedSpies := supportedSpiesWithoutGospy ()
36
+ supportedSpies := spy . SupportedExecSpies ()
36
37
suggestedCommand := fmt .Sprintf ("pyroscope exec -spy-name %s %s" , supportedSpies [0 ], strings .Join (args , " " ))
37
38
return fmt .Errorf (
38
39
"could not automatically find a spy for program \" %s\" . Pass spy name via %s argument, for example: \n %s\n \n Available spies are: %s\n %s\n If you believe this is a mistake, please submit an issue at %s" ,
@@ -69,36 +70,42 @@ func Cli(cfg *config.Config, args []string) error {
69
70
UpstreamThreads : cfg .Exec .UpstreamThreads ,
70
71
UpstreamRequestTimeout : cfg .Exec .UpstreamRequestTimeout ,
71
72
})
73
+ defer u .Stop ()
72
74
73
- // TODO: make configurable?
75
+ // TODO: improve this logic, basically we need a smart way of detecting that an app successfully loaded.
76
+ // Maybe do this on some ticker (every 100 ms) with a timeout (20 s). Make this configurable too
74
77
time .Sleep (5 * time .Second )
75
- // TODO: add sample rate
78
+ // TODO: add sample rate, make it configurable
76
79
sess := agent .NewSession (u , cfg .Exec .ApplicationName , spyName , 100 , cmd .Process .Pid , cfg .Exec .DetectSubprocesses )
77
80
sess .Start ()
78
81
defer sess .Stop ()
79
82
80
- // TODO: very hacky, at some point we'll need to make wait work
81
- // cmd.Wait()
82
-
83
- for {
84
- time .Sleep (time .Second )
85
- p , err := ps .FindProcess (cmd .Process .Pid )
86
- if p == nil || err != nil {
87
- break
88
- }
89
- }
83
+ waitForProcessToExit (cmd )
90
84
return nil
91
85
}
92
86
93
- func supportedSpiesWithoutGospy () []string {
94
- supportedSpies := []string {}
95
- for _ , s := range spy .SupportedSpies {
96
- if s != "gospy" {
97
- supportedSpies = append (supportedSpies , s )
87
+ // TODO: very hacky, at some point we'll need to make `cmd.Wait()` work
88
+ // Currently the issue is that on Linux it often thinks the process exited when it did not.
89
+ func waitForProcessToExit (cmd * exec.Cmd ) {
90
+ sigc := make (chan struct {})
91
+
92
+ atexit .Register (func () {
93
+ sigc <- struct {}{}
94
+ })
95
+
96
+ t := time .NewTicker (time .Second )
97
+ for {
98
+ select {
99
+ case <- sigc :
100
+ cmd .Process .Kill ()
101
+ return
102
+ case <- t .C :
103
+ p , err := ps .FindProcess (cmd .Process .Pid )
104
+ if p == nil || err != nil {
105
+ return
106
+ }
98
107
}
99
108
}
100
-
101
- return supportedSpies
102
109
}
103
110
104
111
func performChecks (spyName string ) error {
@@ -113,7 +120,7 @@ func performChecks(spyName string) error {
113
120
}
114
121
115
122
if ! stringsContains (spy .SupportedSpies , spyName ) {
116
- supportedSpies := supportedSpiesWithoutGospy ()
123
+ supportedSpies := spy . SupportedExecSpies ()
117
124
return fmt .Errorf (
118
125
"Spy \" %s\" is not supported. Available spies are: %s\n %s" ,
119
126
color .BlueString (spyName ),
0 commit comments