Skip to content

Commit 56672a5

Browse files
feat: add priority to spawned process (#103)
1 parent 38f1766 commit 56672a5

File tree

1 file changed

+56
-10
lines changed

1 file changed

+56
-10
lines changed

src/exporter/exporter.go

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,8 @@ type Exporter struct {
3838
jobObject windows.Handle
3939
}
4040

41-
type process struct {
42-
pid int
43-
handle windows.Handle
44-
}
45-
4641
// New create a configured Exporter struct ready to be run
4742
func New(verbose bool, bindAddress string, bindPort string) (*Exporter, error) {
48-
4943
integrationDir, err := filepath.Abs(filepath.Dir(os.Args[0]))
5044
if err != nil {
5145
return nil, fmt.Errorf("failed to create exporter:%v", err)
@@ -66,7 +60,7 @@ func New(verbose bool, bindAddress string, bindPort string) (*Exporter, error) {
6660
"--log.level", exporterLogLevel,
6761
"--log.format", "logger:stderr?json=true",
6862
"--collector.service.use-api", // enable collection using windows API instead of WMI
69-
"--collector.service.services-where", "Name like '%'", //All Added to avoid warn message from Exporter
63+
"--collector.service.services-where", "Name like '%'", // All Added to avoid warn message from Exporter
7064
"--telemetry.addr", exporterURL)
7165

7266
return &Exporter{
@@ -82,13 +76,20 @@ func New(verbose bool, bindAddress string, bindPort string) (*Exporter, error) {
8276
// Run executes the exporter binary
8377
func (e *Exporter) Run() error {
8478
e.redirectLogs()
79+
8580
err := e.cmd.Start()
8681
if err != nil {
8782
return fmt.Errorf("failed to run exporter:%v", err)
8883
}
84+
8985
if err = e.createJobObject(); err != nil {
9086
return fmt.Errorf("failed to create job object:%v", err)
9187
}
88+
89+
if err = e.setProcessPriority(); err != nil {
90+
return fmt.Errorf("failed to exporter process priority class: %w", err)
91+
}
92+
9293
go func() {
9394
e.cmd.Wait()
9495
log.Debug("exporter has stopped")
@@ -119,22 +120,67 @@ func (e *Exporter) createJobObject() error {
119120
uint32(unsafe.Sizeof(jobInfo)),
120121
)
121122
if err != nil {
122-
return fmt.Errorf("failed to set job object info:%v", err)
123+
return fmt.Errorf("failed to set job object info: %v", err)
124+
}
125+
126+
if err = e.assingJobObject(); err != nil {
127+
return fmt.Errorf("failed to assign process to job object: %w", err)
128+
}
129+
130+
return nil
131+
}
132+
133+
func (e *Exporter) assingJobObject() error {
134+
handle, err := e.handle()
135+
if err != nil {
136+
return fmt.Errorf("failed to get proc handle: %v", err)
123137
}
124138

125-
err = windows.AssignProcessToJobObject(e.jobObject, (*process)(unsafe.Pointer(e.cmd.Process)).handle)
139+
err = windows.AssignProcessToJobObject(e.jobObject, handle)
126140
if err != nil {
127141
return fmt.Errorf("failed to assign process to job object:%v", err)
128142
}
129143

130144
return nil
131145
}
132146

147+
func (e *Exporter) handle() (windows.Handle, error) {
148+
var processHandle windows.Handle
149+
if e.cmd.Process == nil {
150+
return processHandle, fmt.Errorf("process cannot be nil pointer")
151+
}
152+
153+
// Using unsafe operation we are using the handle inside os.Process.
154+
processHandle = (*struct {
155+
pid int
156+
handle windows.Handle
157+
})(unsafe.Pointer(e.cmd.Process)).handle
158+
159+
return processHandle, nil
160+
}
161+
162+
// setProcessPriority sets the exporter process priority class to match the integration one.
163+
func (e *Exporter) setProcessPriority() error {
164+
priorityClass, err := windows.GetPriorityClass(windows.CurrentProcess())
165+
if err != nil {
166+
return fmt.Errorf("fail to get priorityClass from current process: %w", err)
167+
}
168+
169+
handle, err := e.handle()
170+
if err != nil {
171+
return fmt.Errorf("failed to get proc handle: %v", err)
172+
}
173+
174+
windows.SetPriorityClass(handle, priorityClass)
175+
176+
return nil
177+
}
178+
133179
// Kill cancel the ctx and close the handle
134180
func (e *Exporter) Kill() {
135181
windows.CloseHandle(e.jobObject)
136182
select {
137-
case <-e.Done: //exporter is not running any more
183+
case <-e.Done: // exporter is not running any more
138184
return
139185
default:
140186
e.cancel()

0 commit comments

Comments
 (0)