Skip to content

Commit 9201b5e

Browse files
Jim Minterruncom
authored andcommitted
Prevent ContainerLogs from hanging if container doesn't run for long
Signed-off-by: Jim Minter <jminter@redhat.com>
1 parent a1e9421 commit 9201b5e

5 files changed

Lines changed: 26 additions & 17 deletions

File tree

daemon/logger/journald/journald.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ import (
1818
const name = "journald"
1919

2020
type journald struct {
21+
mu sync.Mutex
2122
vars map[string]string // additional variables and values to send to the journal along with the log message
2223
readers readerList
24+
closed bool
2325
}
2426

2527
type readerList struct {
26-
mu sync.Mutex
2728
readers map[*logger.LogWatcher]*logger.LogWatcher
2829
}
2930

daemon/logger/journald/read.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,12 @@ import (
163163
)
164164

165165
func (s *journald) Close() error {
166-
s.readers.mu.Lock()
166+
s.mu.Lock()
167+
s.closed = true
167168
for reader := range s.readers.readers {
168169
reader.Close()
169170
}
170-
s.readers.mu.Unlock()
171+
s.mu.Unlock()
171172
return nil
172173
}
173174

@@ -321,9 +322,16 @@ func (s *journald) drainJournal(logWatcher *logger.LogWatcher, config logger.Rea
321322
}
322323

323324
func (s *journald) followJournal(logWatcher *logger.LogWatcher, config logger.ReadConfig, j *C.sd_journal, pfd [2]C.int, cursor *C.char) *C.char {
324-
s.readers.mu.Lock()
325+
s.mu.Lock()
325326
s.readers.readers[logWatcher] = logWatcher
326-
s.readers.mu.Unlock()
327+
if s.closed {
328+
// the journald Logger is closed, presumably because the container has been
329+
// reset. So we shouldn't follow, because we'll never be woken up. But we
330+
// should make one more drainJournal call to be sure we've got all the logs.
331+
// Close pfd[1] so that one drainJournal happens, then cleanup, then return.
332+
C.close(pfd[1])
333+
}
334+
s.mu.Unlock()
327335

328336
newCursor := make(chan *C.char)
329337

@@ -350,21 +358,21 @@ func (s *journald) followJournal(logWatcher *logger.LogWatcher, config logger.Re
350358
}
351359
// Clean up.
352360
C.close(pfd[0])
353-
s.readers.mu.Lock()
361+
s.mu.Lock()
354362
delete(s.readers.readers, logWatcher)
355-
s.readers.mu.Unlock()
363+
s.mu.Unlock()
356364
close(logWatcher.Msg)
357365
newCursor <- cursor
358366
}()
359367
// Wait until we're told to stop.
360368
select {
369+
case cursor = <-newCursor:
361370
case <-logWatcher.WatchClose():
362371
// Notify the other goroutine that its work is done.
363372
C.close(pfd[1])
373+
cursor = <-newCursor
364374
}
365375

366-
cursor = <-newCursor
367-
368376
return cursor
369377
}
370378

daemon/logger/jsonfilelog/jsonfilelog.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type JSONFileLogger struct {
2727
mu sync.Mutex
2828
readers map[*logger.LogWatcher]struct{} // stores the active log followers
2929
extra []byte // json-encoded extra attributes
30+
closed bool
3031
}
3132

3233
func init() {
@@ -137,6 +138,7 @@ func (l *JSONFileLogger) LogPath() string {
137138
// Close closes underlying file and signals all readers to stop.
138139
func (l *JSONFileLogger) Close() error {
139140
l.mu.Lock()
141+
l.closed = true
140142
err := l.writer.Close()
141143
for r := range l.readers {
142144
r.Close()

daemon/logger/jsonfilelog/read.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,7 @@ func (l *JSONFileLogger) readLogs(logWatcher *logger.LogWatcher, config logger.R
8888
}
8989
}
9090

91-
if !config.Follow {
92-
if err := latestFile.Close(); err != nil {
93-
logrus.Errorf("Error closing file: %v", err)
94-
}
91+
if !config.Follow || l.closed {
9592
l.mu.Unlock()
9693
return
9794
}
@@ -100,17 +97,18 @@ func (l *JSONFileLogger) readLogs(logWatcher *logger.LogWatcher, config logger.R
10097
latestFile.Seek(0, os.SEEK_END)
10198
}
10299

100+
notifyRotate := l.writer.NotifyRotate()
101+
defer l.writer.NotifyRotateEvict(notifyRotate)
102+
103103
l.readers[logWatcher] = struct{}{}
104+
104105
l.mu.Unlock()
105106

106-
notifyRotate := l.writer.NotifyRotate()
107107
followLogs(latestFile, logWatcher, notifyRotate, config.Since)
108108

109109
l.mu.Lock()
110110
delete(l.readers, logWatcher)
111111
l.mu.Unlock()
112-
113-
l.writer.NotifyRotateEvict(notifyRotate)
114112
}
115113

116114
func tailFile(f io.ReadSeeker, logWatcher *logger.LogWatcher, tail int, since time.Time) {

daemon/logs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
3939
return logger.ErrReadLogsNotSupported
4040
}
4141

42-
follow := config.Follow && container.IsRunning()
42+
follow := config.Follow && !cLogCreated
4343
tailLines, err := strconv.Atoi(config.Tail)
4444
if err != nil {
4545
tailLines = -1

0 commit comments

Comments
 (0)