From d5a6ba3b8bc849dce85bec694e6cbabe0aef41f9 Mon Sep 17 00:00:00 2001 From: Masahiro Nagano Date: Wed, 15 Jul 2026 23:51:48 +0900 Subject: [PATCH] safeer posfile --- .github/workflows/tagpr.yml | 1 - README.md | 2 +- fpos.go | 20 ++++++++++++++------ go.mod | 4 ++-- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tagpr.yml b/.github/workflows/tagpr.yml index f67df12..9644ce8 100644 --- a/.github/workflows/tagpr.yml +++ b/.github/workflows/tagpr.yml @@ -17,4 +17,3 @@ jobs: id: tagpr env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - diff --git a/README.md b/README.md index f824125..c053981 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ As a library, implement the `Callback` interface and call `Parse` on a `Parser`. ```go cb := &MyParserImpl{} parser := &followparser.Parser{ - WorkDir: "/var/tmp", // where pos files are stored + WorkDir: "/path/to/workdir", // where pos files are stored Callback: cb, // optional: // ArchiveDir: "/var/log/archive", diff --git a/fpos.go b/fpos.go index 963cbb2..e925412 100644 --- a/fpos.go +++ b/fpos.go @@ -77,21 +77,29 @@ func (pf *posFile) write(pos int64, fstat *fStat) error { Inode: fstat.Inode, Dev: fstat.Dev, } - file, err := os.Create(pf.filename) + jb, err := json.Marshal(fp) if err != nil { return err } - defer file.Close() - jb, err := json.Marshal(fp) + // To avoid race condition, we create a temporary file and then rename it to the target filename. + f, err := os.CreateTemp(filepath.Dir(pf.filename), filepath.Base(pf.filename)) if err != nil { return err } - _, err = file.Write(jb) + defer f.Close() + _, err = f.Write(jb) if err != nil { return err } - return file.Sync() - + err = f.Sync() + if err != nil { + return err + } + err = f.Close() + if err != nil { + return err + } + return os.Rename(f.Name(), pf.filename) } func fileStat(filename string) (*fStat, error) { diff --git a/go.mod b/go.mod index d829959..86aedbf 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ -module github.com/kazeburo/followparser +module github.com/monitoring-forge/followparser -go 1.23.4 +go 1.25 require github.com/avast/retry-go/v4 v4.7.0