Prevent ContainerLogs from hanging if container doesn't run for long

Signed-off-by: Jim Minter <jminter@redhat.com>
This commit is contained in:
Jim Minter 2017-03-15 15:41:12 +00:00
parent 68e71aa3e6
commit 4fdb17c777
5 changed files with 26 additions and 17 deletions

View File

@ -18,12 +18,13 @@ import (
const name = "journald"
type journald struct {
mu sync.Mutex
vars map[string]string // additional variables and values to send to the journal along with the log message
readers readerList
closed bool
}
type readerList struct {
mu sync.Mutex
readers map[*logger.LogWatcher]*logger.LogWatcher
}

View File

@ -161,11 +161,12 @@ import (
)
func (s *journald) Close() error {
s.readers.mu.Lock()
s.mu.Lock()
s.closed = true
for reader := range s.readers.readers {
reader.Close()
}
s.readers.mu.Unlock()
s.mu.Unlock()
return nil
}
@ -245,9 +246,16 @@ drain:
}
func (s *journald) followJournal(logWatcher *logger.LogWatcher, config logger.ReadConfig, j *C.sd_journal, pfd [2]C.int, cursor *C.char) *C.char {
s.readers.mu.Lock()
s.mu.Lock()
s.readers.readers[logWatcher] = logWatcher
s.readers.mu.Unlock()
if s.closed {
// the journald Logger is closed, presumably because the container has been
// reset. So we shouldn't follow, because we'll never be woken up. But we
// should make one more drainJournal call to be sure we've got all the logs.
// Close pfd[1] so that one drainJournal happens, then cleanup, then return.
C.close(pfd[1])
}
s.mu.Unlock()
newCursor := make(chan *C.char)
@ -274,22 +282,22 @@ func (s *journald) followJournal(logWatcher *logger.LogWatcher, config logger.Re
// Clean up.
C.close(pfd[0])
s.readers.mu.Lock()
s.mu.Lock()
delete(s.readers.readers, logWatcher)
s.readers.mu.Unlock()
s.mu.Unlock()
close(logWatcher.Msg)
newCursor <- cursor
}()
// Wait until we're told to stop.
select {
case cursor = <-newCursor:
case <-logWatcher.WatchClose():
// Notify the other goroutine that its work is done.
C.close(pfd[1])
cursor = <-newCursor
}
cursor = <-newCursor
return cursor
}

View File

@ -27,6 +27,7 @@ type JSONFileLogger struct {
mu sync.Mutex
readers map[*logger.LogWatcher]struct{} // stores the active log followers
extra []byte // json-encoded extra attributes
closed bool
}
func init() {
@ -142,6 +143,7 @@ func (l *JSONFileLogger) LogPath() string {
// Close closes underlying file and signals all readers to stop.
func (l *JSONFileLogger) Close() error {
l.mu.Lock()
l.closed = true
err := l.writer.Close()
for r := range l.readers {
r.Close()

View File

@ -88,10 +88,7 @@ func (l *JSONFileLogger) readLogs(logWatcher *logger.LogWatcher, config logger.R
}
}
if !config.Follow {
if err := latestFile.Close(); err != nil {
logrus.Errorf("Error closing file: %v", err)
}
if !config.Follow || l.closed {
l.mu.Unlock()
return
}
@ -100,17 +97,18 @@ func (l *JSONFileLogger) readLogs(logWatcher *logger.LogWatcher, config logger.R
latestFile.Seek(0, os.SEEK_END)
}
notifyRotate := l.writer.NotifyRotate()
defer l.writer.NotifyRotateEvict(notifyRotate)
l.readers[logWatcher] = struct{}{}
l.mu.Unlock()
notifyRotate := l.writer.NotifyRotate()
followLogs(latestFile, logWatcher, notifyRotate, config.Since)
l.mu.Lock()
delete(l.readers, logWatcher)
l.mu.Unlock()
l.writer.NotifyRotateEvict(notifyRotate)
}
func tailFile(f io.ReadSeeker, logWatcher *logger.LogWatcher, tail int, since time.Time) {

View File

@ -62,7 +62,7 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c
return nil, logger.ErrReadLogsNotSupported
}
follow := config.Follow && container.IsRunning()
follow := config.Follow && !cLogCreated
tailLines, err := strconv.Atoi(config.Tail)
if err != nil {
tailLines = -1