Signed-off-by: Alexander Morozov <lk4d4@docker.com>
| ... | ... |
@@ -184,21 +184,6 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r * |
| 184 | 184 |
stdout := &streamformatter.StdoutFormatter{Writer: out, StreamFormatter: sf}
|
| 185 | 185 |
stderr := &streamformatter.StderrFormatter{Writer: out, StreamFormatter: sf}
|
| 186 | 186 |
|
| 187 |
- finished := make(chan struct{})
|
|
| 188 |
- defer close(finished) |
|
| 189 |
- if notifier, ok := w.(http.CloseNotifier); ok {
|
|
| 190 |
- notifyContext, cancel := context.WithCancel(ctx) |
|
| 191 |
- closeNotifier := notifier.CloseNotify() |
|
| 192 |
- go func() {
|
|
| 193 |
- select {
|
|
| 194 |
- case <-closeNotifier: |
|
| 195 |
- cancel() |
|
| 196 |
- case <-finished: |
|
| 197 |
- } |
|
| 198 |
- }() |
|
| 199 |
- ctx = notifyContext |
|
| 200 |
- } |
|
| 201 |
- |
|
| 202 | 187 |
imgID, err := br.backend.Build(ctx, buildOptions, |
| 203 | 188 |
builder.DockerIgnoreContext{ModifiableContext: buildContext},
|
| 204 | 189 |
stdout, stderr, out) |
| ... | ... |
@@ -4,6 +4,8 @@ import ( |
| 4 | 4 |
"io" |
| 5 | 5 |
"time" |
| 6 | 6 |
|
| 7 |
+ "golang.org/x/net/context" |
|
| 8 |
+ |
|
| 7 | 9 |
"github.com/docker/docker/api/types/backend" |
| 8 | 10 |
"github.com/docker/docker/pkg/archive" |
| 9 | 11 |
"github.com/docker/docker/pkg/version" |
| ... | ... |
@@ -49,8 +51,8 @@ type stateBackend interface {
|
| 49 | 49 |
type monitorBackend interface {
|
| 50 | 50 |
ContainerChanges(name string) ([]archive.Change, error) |
| 51 | 51 |
ContainerInspect(name string, size bool, version version.Version) (interface{}, error)
|
| 52 |
- ContainerLogs(name string, config *backend.ContainerLogsConfig, started chan struct{}) error
|
|
| 53 |
- ContainerStats(name string, config *backend.ContainerStatsConfig) error |
|
| 52 |
+ ContainerLogs(ctx context.Context, name string, config *backend.ContainerLogsConfig, started chan struct{}) error
|
|
| 53 |
+ ContainerStats(ctx context.Context, name string, config *backend.ContainerStatsConfig) error |
|
| 54 | 54 |
ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) |
| 55 | 55 |
|
| 56 | 56 |
Containers(config *types.ContainerListOptions) ([]*types.Container, error) |
| ... | ... |
@@ -33,8 +33,8 @@ func (r *containerRouter) initRoutes() {
|
| 33 | 33 |
router.NewGetRoute("/containers/{name:.*}/changes", r.getContainersChanges),
|
| 34 | 34 |
router.NewGetRoute("/containers/{name:.*}/json", r.getContainersByName),
|
| 35 | 35 |
router.NewGetRoute("/containers/{name:.*}/top", r.getContainersTop),
|
| 36 |
- router.NewGetRoute("/containers/{name:.*}/logs", r.getContainersLogs),
|
|
| 37 |
- router.NewGetRoute("/containers/{name:.*}/stats", r.getContainersStats),
|
|
| 36 |
+ router.Cancellable(router.NewGetRoute("/containers/{name:.*}/logs", r.getContainersLogs)),
|
|
| 37 |
+ router.Cancellable(router.NewGetRoute("/containers/{name:.*}/stats", r.getContainersStats)),
|
|
| 38 | 38 |
router.NewGetRoute("/containers/{name:.*}/attach/ws", r.wsContainersAttach),
|
| 39 | 39 |
router.NewGetRoute("/exec/{id:.*}/json", r.getExecByID),
|
| 40 | 40 |
router.NewGetRoute("/containers/{name:.*}/archive", r.getContainersArchive),
|
| ... | ... |
@@ -67,19 +67,13 @@ func (s *containerRouter) getContainersStats(ctx context.Context, w http.Respons |
| 67 | 67 |
w.Header().Set("Content-Type", "application/json")
|
| 68 | 68 |
} |
| 69 | 69 |
|
| 70 |
- var closeNotifier <-chan bool |
|
| 71 |
- if notifier, ok := w.(http.CloseNotifier); ok {
|
|
| 72 |
- closeNotifier = notifier.CloseNotify() |
|
| 73 |
- } |
|
| 74 |
- |
|
| 75 | 70 |
config := &backend.ContainerStatsConfig{
|
| 76 | 71 |
Stream: stream, |
| 77 | 72 |
OutStream: w, |
| 78 |
- Stop: closeNotifier, |
|
| 79 | 73 |
Version: string(httputils.VersionFromContext(ctx)), |
| 80 | 74 |
} |
| 81 | 75 |
|
| 82 |
- return s.backend.ContainerStats(vars["name"], config) |
|
| 76 |
+ return s.backend.ContainerStats(ctx, vars["name"], config) |
|
| 83 | 77 |
} |
| 84 | 78 |
|
| 85 | 79 |
func (s *containerRouter) getContainersLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| ... | ... |
@@ -97,11 +91,6 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response |
| 97 | 97 |
return fmt.Errorf("Bad parameters: you must choose at least one stream")
|
| 98 | 98 |
} |
| 99 | 99 |
|
| 100 |
- var closeNotifier <-chan bool |
|
| 101 |
- if notifier, ok := w.(http.CloseNotifier); ok {
|
|
| 102 |
- closeNotifier = notifier.CloseNotify() |
|
| 103 |
- } |
|
| 104 |
- |
|
| 105 | 100 |
containerName := vars["name"] |
| 106 | 101 |
logsConfig := &backend.ContainerLogsConfig{
|
| 107 | 102 |
ContainerLogsOptions: types.ContainerLogsOptions{
|
| ... | ... |
@@ -113,11 +102,10 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response |
| 113 | 113 |
ShowStderr: stderr, |
| 114 | 114 |
}, |
| 115 | 115 |
OutStream: w, |
| 116 |
- Stop: closeNotifier, |
|
| 117 | 116 |
} |
| 118 | 117 |
|
| 119 | 118 |
chStarted := make(chan struct{})
|
| 120 |
- if err := s.backend.ContainerLogs(containerName, logsConfig, chStarted); err != nil {
|
|
| 119 |
+ if err := s.backend.ContainerLogs(ctx, containerName, logsConfig, chStarted); err != nil {
|
|
| 121 | 120 |
select {
|
| 122 | 121 |
case <-chStarted: |
| 123 | 122 |
// The client may be expecting all of the data we're sending to |
| ... | ... |
@@ -18,7 +18,7 @@ func NewRouter(b Backend) router.Router {
|
| 18 | 18 |
r.routes = []router.Route{
|
| 19 | 19 |
router.NewOptionsRoute("/{anyroute:.*}", optionsHandler),
|
| 20 | 20 |
router.NewGetRoute("/_ping", pingHandler),
|
| 21 |
- router.NewGetRoute("/events", r.getEvents),
|
|
| 21 |
+ router.Cancellable(router.NewGetRoute("/events", r.getEvents)),
|
|
| 22 | 22 |
router.NewGetRoute("/info", r.getInfo),
|
| 23 | 23 |
router.NewGetRoute("/version", r.getVersion),
|
| 24 | 24 |
router.NewPostRoute("/auth", r.postAuth),
|
| ... | ... |
@@ -83,11 +83,6 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r * |
| 83 | 83 |
} |
| 84 | 84 |
} |
| 85 | 85 |
|
| 86 |
- var closeNotify <-chan bool |
|
| 87 |
- if closeNotifier, ok := w.(http.CloseNotifier); ok {
|
|
| 88 |
- closeNotify = closeNotifier.CloseNotify() |
|
| 89 |
- } |
|
| 90 |
- |
|
| 91 | 86 |
for {
|
| 92 | 87 |
select {
|
| 93 | 88 |
case ev := <-l: |
| ... | ... |
@@ -101,8 +96,8 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r * |
| 101 | 101 |
} |
| 102 | 102 |
case <-timer.C: |
| 103 | 103 |
return nil |
| 104 |
- case <-closeNotify: |
|
| 105 |
- logrus.Debug("Client disconnected, stop sending events")
|
|
| 104 |
+ case <-ctx.Done(): |
|
| 105 |
+ logrus.Debug("Client context cancelled, stop sending events")
|
|
| 106 | 106 |
return nil |
| 107 | 107 |
} |
| 108 | 108 |
} |
| ... | ... |
@@ -31,7 +31,6 @@ type ContainerAttachConfig struct {
|
| 31 | 31 |
type ContainerLogsConfig struct {
|
| 32 | 32 |
types.ContainerLogsOptions |
| 33 | 33 |
OutStream io.Writer |
| 34 |
- Stop <-chan bool |
|
| 35 | 34 |
} |
| 36 | 35 |
|
| 37 | 36 |
// ContainerStatsConfig holds information for configuring the runtime |
| ... | ... |
@@ -39,7 +38,6 @@ type ContainerLogsConfig struct {
|
| 39 | 39 |
type ContainerStatsConfig struct {
|
| 40 | 40 |
Stream bool |
| 41 | 41 |
OutStream io.Writer |
| 42 |
- Stop <-chan bool |
|
| 43 | 42 |
Version string |
| 44 | 43 |
} |
| 45 | 44 |
|
| ... | ... |
@@ -6,6 +6,8 @@ import ( |
| 6 | 6 |
"strconv" |
| 7 | 7 |
"time" |
| 8 | 8 |
|
| 9 |
+ "golang.org/x/net/context" |
|
| 10 |
+ |
|
| 9 | 11 |
"github.com/Sirupsen/logrus" |
| 10 | 12 |
"github.com/docker/docker/api/types/backend" |
| 11 | 13 |
"github.com/docker/docker/container" |
| ... | ... |
@@ -19,7 +21,7 @@ import ( |
| 19 | 19 |
|
| 20 | 20 |
// ContainerLogs hooks up a container's stdout and stderr streams |
| 21 | 21 |
// configured with the given struct. |
| 22 |
-func (daemon *Daemon) ContainerLogs(containerName string, config *backend.ContainerLogsConfig, started chan struct{}) error {
|
|
| 22 |
+func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, config *backend.ContainerLogsConfig, started chan struct{}) error {
|
|
| 23 | 23 |
container, err := daemon.GetContainer(containerName) |
| 24 | 24 |
if err != nil {
|
| 25 | 25 |
return err |
| ... | ... |
@@ -78,7 +80,7 @@ func (daemon *Daemon) ContainerLogs(containerName string, config *backend.Contai |
| 78 | 78 |
case err := <-logs.Err: |
| 79 | 79 |
logrus.Errorf("Error streaming logs: %v", err)
|
| 80 | 80 |
return nil |
| 81 |
- case <-config.Stop: |
|
| 81 |
+ case <-ctx.Done(): |
|
| 82 | 82 |
logs.Close() |
| 83 | 83 |
return nil |
| 84 | 84 |
case msg, ok := <-logs.Msg: |
| ... | ... |
@@ -5,6 +5,8 @@ import ( |
| 5 | 5 |
"errors" |
| 6 | 6 |
"runtime" |
| 7 | 7 |
|
| 8 |
+ "golang.org/x/net/context" |
|
| 9 |
+ |
|
| 8 | 10 |
"github.com/docker/docker/api/types/backend" |
| 9 | 11 |
"github.com/docker/docker/pkg/ioutils" |
| 10 | 12 |
"github.com/docker/docker/pkg/version" |
| ... | ... |
@@ -14,7 +16,7 @@ import ( |
| 14 | 14 |
|
| 15 | 15 |
// ContainerStats writes information about the container to the stream |
| 16 | 16 |
// given in the config object. |
| 17 |
-func (daemon *Daemon) ContainerStats(prefixOrName string, config *backend.ContainerStatsConfig) error {
|
|
| 17 |
+func (daemon *Daemon) ContainerStats(ctx context.Context, prefixOrName string, config *backend.ContainerStatsConfig) error {
|
|
| 18 | 18 |
if runtime.GOOS == "windows" {
|
| 19 | 19 |
return errors.New("Windows does not support stats")
|
| 20 | 20 |
} |
| ... | ... |
@@ -114,7 +116,7 @@ func (daemon *Daemon) ContainerStats(prefixOrName string, config *backend.Contai |
| 114 | 114 |
if !config.Stream {
|
| 115 | 115 |
return nil |
| 116 | 116 |
} |
| 117 |
- case <-config.Stop: |
|
| 117 |
+ case <-ctx.Done(): |
|
| 118 | 118 |
return nil |
| 119 | 119 |
} |
| 120 | 120 |
} |