Skip to content

Commit 6cc2eed

Browse files
committed
HTTP mode: implement exec_timeout via context/cancel
Signed-off-by: Alex Ellis <[email protected]>
1 parent d15d3b6 commit 6cc2eed

File tree

2 files changed

+43
-13
lines changed

2 files changed

+43
-13
lines changed

executor/http_runner.go

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package executor
22

33
import (
4+
"context"
45
"io"
56
"io/ioutil"
67
"log"
@@ -15,15 +16,18 @@ import (
1516

1617
// HTTPFunctionRunner creates and maintains one process responsible for handling all calls
1718
type HTTPFunctionRunner struct {
18-
Process string
19-
ProcessArgs []string
20-
Command *exec.Cmd
21-
StdinPipe io.WriteCloser
22-
StdoutPipe io.ReadCloser
23-
Stderr io.Writer
24-
Mutex sync.Mutex
25-
Client *http.Client
26-
UpstreamURL *url.URL
19+
ExecTimeout time.Duration // ExecTimeout the maxmium duration or an upstream function call
20+
ReadTimeout time.Duration
21+
WriteTimeout time.Duration
22+
Process string
23+
ProcessArgs []string
24+
Command *exec.Cmd
25+
StdinPipe io.WriteCloser
26+
StdoutPipe io.ReadCloser
27+
Stderr io.Writer
28+
Mutex sync.Mutex
29+
Client *http.Client
30+
UpstreamURL *url.URL
2731
}
2832

2933
// Start forks the process used for processing incoming requests
@@ -77,8 +81,7 @@ func (f *HTTPFunctionRunner) Start() error {
7781
}
7882
}()
7983

80-
dialTimeout := 3 * time.Second
81-
f.Client = makeProxyClient(dialTimeout)
84+
f.Client = makeProxyClient(f.ExecTimeout)
8285

8386
urlValue, upstreamURLErr := url.Parse(os.Getenv("upstream_url"))
8487
if upstreamURLErr != nil {
@@ -97,11 +100,37 @@ func (f *HTTPFunctionRunner) Run(req FunctionRequest, contentLength int64, r *ht
97100
for h := range r.Header {
98101
request.Header.Set(h, r.Header.Get(h))
99102
}
103+
ctx, cancel := context.WithTimeout(context.Background(), f.ExecTimeout)
104+
defer cancel()
100105

101-
res, err := f.Client.Do(request)
106+
res, err := f.Client.Do(request.WithContext(ctx))
102107

103108
if err != nil {
104-
log.Println(err)
109+
log.Printf("Upstream HTTP request error: %s\n", err.Error())
110+
111+
// Error unrelated to context / deadline
112+
if ctx.Err() == nil {
113+
w.WriteHeader(http.StatusInternalServerError)
114+
115+
return nil
116+
}
117+
118+
select {
119+
case <-ctx.Done():
120+
{
121+
if ctx.Err() != nil {
122+
// Error due to timeout / deadline
123+
log.Printf("Upstream HTTP killed due to exec_timeout: %s\n", f.ExecTimeout)
124+
125+
w.WriteHeader(http.StatusGatewayTimeout)
126+
return nil
127+
}
128+
129+
}
130+
}
131+
132+
w.WriteHeader(http.StatusInternalServerError)
133+
return err
105134
}
106135

107136
for h := range res.Header {

main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ func getEnvironment(r *http.Request) []string {
197197
func makeHTTPRequestHandler(watchdogConfig config.WatchdogConfig) func(http.ResponseWriter, *http.Request) {
198198
commandName, arguments := watchdogConfig.Process()
199199
functionInvoker := executor.HTTPFunctionRunner{
200+
ExecTimeout: watchdogConfig.ExecTimeout,
200201
Process: commandName,
201202
ProcessArgs: arguments,
202203
}

0 commit comments

Comments
 (0)