Skip to content

Commit

Permalink
sdjournal: SeekTail should be followed by Previous, not Next
Browse files Browse the repository at this point in the history
sd_journal_next is supposed to return 0 (i.e. EOF) if called at the
end of the journal, which would make this issue immediately
apparent. However, there is an open bug that causes it to advance
to the *wrong* message instead (not the last one in the journal)
after a call to sd_journal_seek_tail, which causes code which
follows the documented use here to produce non-obviously incorrect
results (see <systemd/systemd#9934>).

Instead, sd_journal_previous will correctly seek to the last
journal entry, with the unavoidable race condition that it may not
actually be the last entry if the journal is written to between
calls to sd_journal_seek_tail and sd_journal_previous.

This can be verified by comparing the output of `journalctl -o json
| tail -1 | jq -r .MESSAGE_ID` with that of the following simple Go
program

```
package main

import (
        "fmt"

        "github.com/coreos/go-systemd/sdjournal"
)

func main() {
        j, err := sdjournal.NewJournal()
        if err != nil {
                panic(err)
        }

        err = j.SeekTail()
        if err != nil {
                panic(err)
        }

        n, err := j.Previous()
        if err != nil {
                panic(err)
        }

        fmt.Printf("went back by %d\n", n)

        e, err := j.GetEntry()
        if err != nil {
                panic(err)
        }

        fmt.Printf("found message id %s\n", e.Fields["MESSAGE_ID"])
}
```

and noting that the message IDs are equal (again, with an
unavoidable race condition if a message is written in between).
  • Loading branch information
stevenjm committed Oct 21, 2020
1 parent 408310d commit cf46fcf
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 3 deletions.
2 changes: 1 addition & 1 deletion sdjournal/journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ func (j *Journal) SeekHead() error {
}

// SeekTail may be used to seek to the end of the journal, i.e. the most recent
// available entry. This call must be followed by a call to Next before any
// available entry. This call must be followed by a call to Previous before any
// call to Get* will return data about the last element.
func (j *Journal) SeekTail() error {
sd_journal_seek_tail, err := getFunction("sd_journal_seek_tail")
Expand Down
4 changes: 2 additions & 2 deletions sdjournal/journal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ func TestJournalWait(t *testing.T) {
if err := j.SeekTail(); err != nil {
t.Fatalf("Error seeking to tail: %s", err)
}
if _, err := j.Next(); err != nil {
t.Fatalf("Error retrieving next entry: %s", err)
if _, err := j.Previous(); err != nil {
t.Fatalf("Error retrieving previous entry: %s", err)
}

var t1, t2 time.Time
Expand Down

0 comments on commit cf46fcf

Please sign in to comment.