[elbe-devel] [PATCH] log: Fix async_logging()

Torben Hohn torben.hohn at linutronix.de
Wed Jun 3 10:48:34 CEST 2020


On Tue, Jun 02, 2020 at 06:12:24PM -0400, Olivier Dion wrote:
> There was a nasty bug in async_logging() that make it spin forever and
> burn time on the cpu.  Basically after the pipe breaks itself, the
> thread would enter an infinite loop if there's no newline terminating
> the stream.
> 
> This commit fixes that by removing the epoll stuff and detecting the
> broken pipe by reading the empty string from it.
> 
> Also since we're there, I augmented the atmost size up to 4096 bytes
> instead of 80.  This should make logging a little more fluid.
> 
> Signed-off-by: Olivier Dion <dion at linutronix.de>

Reviewed-by: Torben Hohn <torben.hohn at linutronix.de>

> ---
>  elbepack/log.py | 57 +++++++++++++++++++++++--------------------------
>  1 file changed, 27 insertions(+), 30 deletions(-)
> 
> diff --git a/elbepack/log.py b/elbepack/log.py
> index f17df9e7..46ade295 100644
> --- a/elbepack/log.py
> +++ b/elbepack/log.py
> @@ -7,7 +7,6 @@
>  import collections
>  import logging
>  import os
> -import select
>  import threading
>  from contextlib import contextmanager
>  
> @@ -220,7 +219,6 @@ class AsyncLogging(object):
>  
>      def __init__(self, atmost, stream, block):
>          self.lines = []
> -        self.epoll = select.epoll()
>          self.atmost = atmost
>          self.fd = None
>          calling_thread = threading.current_thread().ident
> @@ -231,7 +229,6 @@ class AsyncLogging(object):
>  
>      def __call__(self, r, w):
>          os.close(w)
> -        self.epoll.register(r, select.EPOLLIN | select.EPOLLHUP)
>          self.fd = r
>          try:
>              self.run()
> @@ -239,41 +236,41 @@ class AsyncLogging(object):
>              os.close(r)
>  
>      def run(self):
> -        alive = True
>          rest = bytes()
> -        while alive:
> -            events = self.epoll.poll()
> -            for _, event in events:
> -                if event & select.EPOLLIN:
> -                    rest = self.read(rest)
> -                if event & select.EPOLLHUP:
> -                    alive = False
> -
> -        # Reading rest after pipe hang up
> +
>          while True:
> -            rest = self.read(rest)
> -            if not rest:
> +
> +            buf  = os.read(self.fd, self.atmost)
> +
> +            # Pipe broke
> +            if not buf:
>                  break
>  
> +            buf = rest + buf
> +            cnt = 0
> +            j   = 0
> +
> +            # Line buffering
> +            for i in range(len(buf)):
> +                if buf[i] == '\n':
> +                    self.lines.append(buf[j:i])
> +                    cnt += 1
> +                    j = i + 1
> +
> +            # Log the line now for echo back
> +            if cnt:
> +                self.stream.info("\n".join(self.lines[-cnt:]))
> +
> +            # Keep rest for next line buffering
> +            rest = buf[j:]
> +
>          if self.lines:
>              self.lines[-1] += rest
>              self.block.info("\n".join(self.lines))
>  
> -    def read(self, rest):
> -        buff = rest + os.read(self.fd, self.atmost)
> -        j = 0
> -        count = 0
> -        for i in range(len(buff)):
> -            if buff[i] == '\n':
> -                self.lines.append(buff[j:i])
> -                count += 1
> -                j = i + 1
> -        if count:
> -            self.stream.info("\n".join(self.lines[-count:]))
> -        return buff[j:]
> -
> -
> -def async_logging(r, w, stream, block, atmost=80):
> +
> +
> +def async_logging(r, w, stream, block, atmost=4096):
>      t = threading.Thread(target=AsyncLogging(atmost, stream, block),
>                           args=(r, w))
>      t.daemon = True
> -- 
> 2.27.0
> 
> 
> _______________________________________________
> elbe-devel mailing list
> elbe-devel at linutronix.de
> https://lists.linutronix.de/mailman/listinfo/elbe-devel

-- 
Torben Hohn
Linutronix GmbH | Bahnhofstrasse 3 | D-88690 Uhldingen-Mühlhofen
Phone: +49 7556 25 999 18; Fax.: +49 7556 25 999 99

Hinweise zum Datenschutz finden Sie hier (Informations on data privacy 
can be found here): https://linutronix.de/kontakt/Datenschutz.php

Linutronix GmbH | Firmensitz (Registered Office): Uhldingen-Mühlhofen | 
Registergericht (Registration Court): Amtsgericht Freiburg i.Br., HRB700 
806 | Geschäftsführer (Managing Directors): Heinz Egger, Thomas Gleixner



More information about the elbe-devel mailing list