-
Notifications
You must be signed in to change notification settings - Fork 1k
/
process_endpoint.go
104 lines (92 loc) · 2.46 KB
/
process_endpoint.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Copyright 2013 Joe Walnes and the websocketd team.
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package libwebsocketd
import (
"bufio"
"io"
"syscall"
)
type ProcessEndpoint struct {
process *LaunchedProcess
bufferedIn *bufio.Writer
output chan string
log *LogScope
}
func NewProcessEndpoint(process *LaunchedProcess, log *LogScope) *ProcessEndpoint {
return &ProcessEndpoint{
process: process,
bufferedIn: bufio.NewWriter(process.stdin),
output: make(chan string),
log: log}
}
func (pe *ProcessEndpoint) Terminate() {
pe.process.stdin.Close()
err := pe.process.cmd.Process.Signal(syscall.SIGINT)
if err != nil {
pe.log.Debug("process", "Failed to Interupt process %v: %s, attempting to kill", pe.process.cmd.Process.Pid, err)
err = pe.process.cmd.Process.Kill()
if err != nil {
pe.log.Debug("process", "Failed to Kill process %v: %s", pe.process.cmd.Process.Pid, err)
}
}
pe.process.cmd.Wait()
if err != nil {
pe.log.Debug("process", "Failed to reap process %v: %s", pe.process.cmd.Process.Pid, err)
}
}
func (pe *ProcessEndpoint) Output() chan string {
return pe.output
}
func (pe *ProcessEndpoint) Send(msg string) bool {
pe.bufferedIn.WriteString(msg)
pe.bufferedIn.WriteString("\n")
pe.bufferedIn.Flush()
return true
}
func (pe *ProcessEndpoint) ReadOutput(input io.ReadCloser, config *Config) {
bufin := bufio.NewReader(input)
for {
str, err := bufin.ReadString('\n')
if err != nil {
if err != io.EOF {
pe.log.Error("process", "Unexpected STDOUT read from process: %s", err)
} else {
pe.log.Debug("process", "Process STDOUT closed")
}
break
}
pe.output <- trimEOL(str)
}
close(pe.output)
}
func (pe *ProcessEndpoint) pipeStdErr(config *Config) {
bufstderr := bufio.NewReader(pe.process.stderr)
for {
str, err := bufstderr.ReadString('\n')
if err != nil {
if err != io.EOF {
pe.log.Error("process", "Unexpected STDERR read from process: %s", err)
} else {
pe.log.Debug("process", "Process STDERR closed")
}
break
}
pe.log.Error("stderr", "%s", trimEOL(str))
}
}
func trimEOL(s string) string {
// Handles unixy style \n and windowsy style \r\n
trimCount := 0
if len(s) > 0 && s[len(s)-1] == '\n' {
trimCount = 1
if len(s) > 1 && s[len(s)-2] == '\r' {
trimCount = 2
}
}
if trimCount == 0 {
return s
}
return s[0 : len(s)-trimCount]
}