diff --git a/libpod/container_log.go b/libpod/container_log.go
index a9e0fe0658..c49b54eb16 100644
--- a/libpod/container_log.go
+++ b/libpod/container_log.go
@@ -10,6 +10,7 @@ import (
 	"github.com/containers/podman/v4/libpod/define"
 	"github.com/containers/podman/v4/libpod/events"
 	"github.com/containers/podman/v4/libpod/logs"
+	"github.com/nxadm/tail"
 	"github.com/nxadm/tail/watch"
 	"github.com/sirupsen/logrus"
 )
@@ -74,14 +75,19 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
 
 	go func() {
 		defer options.WaitGroup.Done()
-
-		for line := range t.Lines {
+		var line *tail.Line
+		var ok bool
+		for {
 			select {
 			case <-ctx.Done():
 				// the consumer has cancelled
+				t.Kill(errors.New("hangup by client"))
 				return
-			default:
-				// fallthrough
+			case line, ok = <-t.Lines:
+				if !ok {
+					// channel was closed
+					return
+				}
 			}
 			nll, err := logs.NewLogLine(line.Text)
 			if err != nil {
diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go
index 0686caed29..7e95f2449f 100644
--- a/libpod/container_log_linux.go
+++ b/libpod/container_log_linux.go
@@ -178,8 +178,13 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
 				if !options.Follow || !containerCouldBeLogging {
 					return
 				}
-				// Sleep until something's happening on the journal.
-				journal.Wait(sdjournal.IndefiniteWait)
+
+				// journal.Wait() is blocking, this would cause the goroutine to hang forever
+				// if no more journal entries are generated and thus if the client
+				// has closed the connection in the meantime to leak memory.
+				// Waiting only 5 seconds makes sure we can check if the client closed in the
+				// meantime at least every 5 seconds.
+				journal.Wait(5 * time.Second)
 				continue
 			}
 			lastReadCursor = cursor
diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go
index 0a0a768d0e..16ef6504f2 100644
--- a/libpod/events/journal_linux.go
+++ b/libpod/events/journal_linux.go
@@ -141,9 +141,18 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error {
 			if !options.Stream || (len(options.Until) > 0 && time.Now().After(untilTime)) {
 				break
 			}
-			t := sdjournal.IndefiniteWait
+
+			// j.Wait() is blocking, this would cause the goroutine to hang forever
+			// if no more journal entries are generated and thus if the client
+			// has closed the connection in the meantime to leak memory.
+			// Waiting only 5 seconds makes sure we can check if the client closed in the
+			// meantime at least every 5 seconds.
+			t := 5 * time.Second
 			if len(options.Until) > 0 {
-				t = time.Until(untilTime)
+				until := time.Until(untilTime)
+				if until < t {
+					t = until
+				}
 			}
 			_ = j.Wait(t)
 			continue
diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go
index 4dafd8600c..c7dbf48501 100644
--- a/libpod/events/logfile.go
+++ b/libpod/events/logfile.go
@@ -108,23 +108,19 @@ func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error {
 			}
 		}()
 	}
-	funcDone := make(chan bool)
-	copy := true
-	go func() {
-		select {
-		case <-funcDone:
-			// Do nothing
-		case <-ctx.Done():
-			copy = false
-			t.Kill(errors.New("hangup by client"))
-		}
-	}()
-	for line := range t.Lines {
+	var line *tail.Line
+	var ok bool
+	for {
 		select {
 		case <-ctx.Done():
 			// the consumer has cancelled
+			t.Kill(errors.New("hangup by client"))
 			return nil
-		default:
+		case line, ok = <-t.Lines:
+			if !ok {
+				// channel was closed
+				return nil
+			}
 			// fallthrough
 		}
 
@@ -138,12 +134,10 @@ func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error {
 		default:
 			return fmt.Errorf("event type %s is not valid in %s", event.Type.String(), e.options.LogFilePath)
 		}
-		if copy && applyFilters(event, filterMap) {
+		if applyFilters(event, filterMap) {
 			options.EventChannel <- event
 		}
 	}
-	funcDone <- true
-	return nil
 }
 
 // String returns a string representation of the logger