From ebbe57d0ab38ab2f27b75a83efa8459dc88a2612 Mon Sep 17 00:00:00 2001 From: ardevd Date: Tue, 3 Jun 2025 07:39:21 +0200 Subject: [PATCH 1/4] fix(syncthing): avoid writing panic log to nil fd (#10154) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Purpose This change fixes a logical bug in the panic log writing where we could end up writing to a uninitialized file descriptor. On the very first iteration, `panicFd` is nil. We enter the if `panicFd == nil { … }` block, check for “panic:” or “fatal error:”, and if neither matches, we skip instantiating `panicFd` altogether. However, immediately after, still within `if panicFd == nil { … }`, we call `panicFd.WriteString("Panic at ...")`. But `panicFd` would in this case be `nil`, which will cause a run‐time panic. It's not clear to me why panicFd is only initialized if the lines start with "panic:" or "fatal error:" so I've left that logic untouched. With this change we at least avoid the risk of writing to a nil filedescriptor. ## Authorship Your name and email will be added automatically to the AUTHORS file based on the commit metadata. --------- Co-authored-by: Jakob Borg --- cmd/syncthing/monitor.go | 48 +++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/cmd/syncthing/monitor.go b/cmd/syncthing/monitor.go index f91ee8323..932ae1309 100644 --- a/cmd/syncthing/monitor.go +++ b/cmd/syncthing/monitor.go @@ -238,19 +238,18 @@ func copyStderr(stderr io.Reader, dst io.Writer) { return } - if panicFd == nil { - dst.Write([]byte(line)) + dst.Write([]byte(line)) - if strings.HasPrefix(line, "panic:") || strings.HasPrefix(line, "fatal error:") { - panicFd, err = os.Create(locations.GetTimestamped(locations.PanicLog)) - if err != nil { - l.Warnln("Create panic log:", err) - continue - } + if panicFd == nil && (strings.HasPrefix(line, "panic:") || strings.HasPrefix(line, "fatal error:")) { + panicFd, err = os.Create(locations.GetTimestamped(locations.PanicLog)) + if err != nil { + l.Warnln("Create panic log:", err) + continue + } - l.Warnf("Panic detected, writing to \"%s\"", panicFd.Name()) - if strings.Contains(line, "leveldb") && strings.Contains(line, "corrupt") { - l.Warnln(` + l.Warnf("Panic detected, writing to \"%s\"", panicFd.Name()) + if strings.Contains(line, "leveldb") && strings.Contains(line, "corrupt") { + l.Warnln(` ********************************************************************************* * Crash due to corrupt database. * * * @@ -263,22 +262,21 @@ func copyStderr(stderr io.Reader, dst io.Writer) { * https://docs.syncthing.net/users/faq.html#my-syncthing-database-is-corrupt * ********************************************************************************* `) - } else { - l.Warnln("Please check for existing issues with similar panic message at https://github.com/syncthing/syncthing/issues/") - l.Warnln("If no issue with similar panic message exists, please create a new issue with the panic log attached") - } - - stdoutMut.Lock() - for _, line := range stdoutFirstLines { - panicFd.WriteString(line) - } - panicFd.WriteString("...\n") - for _, line := range stdoutLastLines { - panicFd.WriteString(line) - } - stdoutMut.Unlock() + } else { + l.Warnln("Please check for existing issues with similar panic message at https://github.com/syncthing/syncthing/issues/") + l.Warnln("If no issue with similar panic message exists, please create a new issue with the panic log attached") } + stdoutMut.Lock() + for _, line := range stdoutFirstLines { + panicFd.WriteString(line) + } + panicFd.WriteString("...\n") + for _, line := range stdoutLastLines { + panicFd.WriteString(line) + } + stdoutMut.Unlock() + panicFd.WriteString("Panic at " + time.Now().Format(time.RFC3339) + "\n") } From 21da0d7890e3ea7b017cc1b48a80272af9c5be4a Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Sat, 24 May 2025 08:24:18 +0200 Subject: [PATCH 2/4] fix(stupgrades): return latest stable & pre for each major --- cmd/infra/stupgrades/main.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/cmd/infra/stupgrades/main.go b/cmd/infra/stupgrades/main.go index 0549a3022..2a794e370 100644 --- a/cmd/infra/stupgrades/main.go +++ b/cmd/infra/stupgrades/main.go @@ -201,17 +201,21 @@ func (p *proxy) ServeHTTP(w http.ResponseWriter, req *http.Request) { // looking for a prerelease at all. func filterForLatest(rels []upgrade.Release) []upgrade.Release { var filtered []upgrade.Release - var havePre bool + havePre := make(map[string]bool) + haveStable := make(map[string]bool) for _, rel := range rels { - if !rel.Prerelease { - // We found a stable version, we're good now. + major, _, _ := strings.Cut(rel.Tag, ".") + if !rel.Prerelease && !haveStable[major] { + // Remember the first non-pre for each major filtered = append(filtered, rel) - break + haveStable[major] = true + continue } - if rel.Prerelease && !havePre { - // We remember the first prerelease we find. + if rel.Prerelease && !havePre[major] && !haveStable[major] { + // We remember the first prerelease we find, unless we've + // already found a non-pre of the same major. filtered = append(filtered, rel) - havePre = true + havePre[major] = true } } return filtered From 67ba20d7774d0a72e42ea1319c6e64c8de0905d6 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Thu, 5 Jun 2025 09:53:38 +0200 Subject: [PATCH 3/4] build: also create relaysrv and discosrv releases --- .github/workflows/build-syncthing.yaml | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-syncthing.yaml b/.github/workflows/build-syncthing.yaml index 10e18f8ea..48a650939 100644 --- a/.github/workflows/build-syncthing.yaml +++ b/.github/workflows/build-syncthing.yaml @@ -787,7 +787,7 @@ jobs: with: args: sync -v objstore:release/${{ env.VERSION }} objstore:release/latest - - name: Create GitHub release and push binaries + - name: Create GitHub releases and push binaries run: | maybePrerelease="" if [[ $VERSION == *-* ]]; then @@ -795,8 +795,7 @@ jobs: fi export GH_PROMPT_DISABLED=1 if ! gh release view --json name "$VERSION" >/dev/null 2>&1 ; then - gh release create \ - "$VERSION" \ + gh release create "$VERSION" \ $maybePrerelease \ --title "$VERSION" \ --notes-from-tag @@ -805,9 +804,24 @@ jobs: packages/*.asc packages/*.json \ packages/syncthing-*.tar.gz \ packages/syncthing-*.zip \ - packages/syncthing*.deb + packages/syncthing_*.deb + + PKGS=$(pwd)/packages + cd /tmp # gh will not release for repo x while inside repo y + for repo in relaysrv discosrv ; do + export GH_REPO="syncthing/$repo" + if ! gh release view --json name "$VERSION" >/dev/null 2>&1 ; then + gh release create "$VERSION" \ + $maybePrerelease \ + --title "$VERSION" \ + --notes "https://github.com/syncthing/syncthing/releases/tag/$VERSION" + fi + gh release upload "$VERSION" \ + $PKGS/*.asc \ + $PKGS/*${repo}* + done env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.ACTIONS_GITHUB_TOKEN }} # # Push Debian/APT archive From e9133ef82bf4cea631c768139875e8c56bcb427b Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Thu, 5 Jun 2025 19:18:46 +0200 Subject: [PATCH 4/4] docs: link to Docker image, APT, in release notes --- relnotes/v1.md | 7 +++++++ script/relnotes.go | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/relnotes/v1.md b/relnotes/v1.md index 0345719a0..ec7d8c007 100644 --- a/relnotes/v1.md +++ b/relnotes/v1.md @@ -6,3 +6,10 @@ protocol compatible with Syncthing 1. More detailed information about Syncthing 2 can be found in the release notes at https://github.com/syncthing/syncthing/releases. + +This release is also available as: + +* APT repository: https://apt.syncthing.net/ + +* Docker image: `docker.io/syncthing/syncthing:{{.version}}` or `ghcr.io/syncthing/syncthing:{{.version}}` + (`{docker,ghcr}.io/syncthing/syncthing:1` to follow just the major version) diff --git a/script/relnotes.go b/script/relnotes.go index 3296e6dab..a1b97f844 100644 --- a/script/relnotes.go +++ b/script/relnotes.go @@ -22,6 +22,7 @@ import ( "os" "regexp" "strings" + "text/template" ) var ( @@ -59,12 +60,24 @@ func main() { // Load potential additional release notes from within the repo func additionalNotes(newVer string) ([]string, error) { + data := map[string]string{ + "version": strings.TrimLeft(newVer, "v"), + } + var notes []string ver, _, _ := strings.Cut(newVer, "-") for { file := fmt.Sprintf("relnotes/%s.md", ver) if bs, err := os.ReadFile(file); err == nil { - notes = append(notes, strings.TrimSpace(string(bs))) + tpl, err := template.New("notes").Parse(string(bs)) + if err != nil { + return nil, err + } + buf := new(bytes.Buffer) + if err := tpl.Execute(buf, data); err != nil { + return nil, err + } + notes = append(notes, strings.TrimSpace(buf.String())) } else if !os.IsNotExist(err) { return nil, err }