mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Prevent ContainerLogs from hanging if container doesn't run for long
Signed-off-by: Jim Minter <jminter@redhat.com>
This commit is contained in:
parent
68e71aa3e6
commit
4fdb17c777
5 changed files with 26 additions and 17 deletions
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue