From 42ce6be9b90981917af85274315a8da07924429c Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Tue, 11 Jun 2019 08:19:11 +0200 Subject: [PATCH] lib/ur: Implement crash (panic) reporting (fixes #959) (#5702) * lib/ur: Implement crash (panic) reporting (fixes #959) This implements a simple crash reporting method. It piggybacks on the panic log files created by the monitor process, picking these up and uploading them from the usage reporting routine. A new config value points to the crash receiver base URL, which defaults to "https://crash.syncthing.net/newcrash" (following the pattern of "https://data.syncthing.net/newdata" for usage reports, but allowing us to separate the service as required). --- cmd/stcrashreceiver/_testdata/panic.log | 1172 +++++++++++++++++ cmd/stcrashreceiver/sentry.go | 160 +++ cmd/stcrashreceiver/sentry_test.go | 64 + cmd/stcrashreceiver/stcrashreceiver.go | 135 ++ cmd/syncthing/crash_reporting.go | 152 +++ cmd/syncthing/crash_reporting_test.go | 37 + cmd/syncthing/monitor.go | 48 + go.mod | 3 + go.sum | 9 + gui/default/syncthing/core/notifications.html | 47 + .../syncthing/core/syncthingController.js | 5 + lib/config/config.go | 2 +- lib/config/config_test.go | 22 +- lib/config/migrations.go | 14 + lib/config/migrations_test.go | 34 + lib/config/optionsconfiguration.go | 12 +- lib/config/testdata/overridenvalues.xml | 9 +- lib/config/testdata/v29.xml | 16 + lib/ur/usage_report.go | 3 +- 19 files changed, 1925 insertions(+), 19 deletions(-) create mode 100644 cmd/stcrashreceiver/_testdata/panic.log create mode 100644 cmd/stcrashreceiver/sentry.go create mode 100644 cmd/stcrashreceiver/sentry_test.go create mode 100644 cmd/stcrashreceiver/stcrashreceiver.go create mode 100644 cmd/syncthing/crash_reporting.go create mode 100644 cmd/syncthing/crash_reporting_test.go create mode 100644 lib/config/migrations_test.go create mode 100644 lib/config/testdata/v29.xml diff --git a/cmd/stcrashreceiver/_testdata/panic.log b/cmd/stcrashreceiver/_testdata/panic.log new file mode 100644 index 000000000..7e5a9560c --- /dev/null +++ b/cmd/stcrashreceiver/_testdata/panic.log @@ -0,0 +1,1172 @@ +09:12:41 INFO: syncthing v1.1.3+39-g62a6d619e-dirty "Erbium Earthworm" (go1.12.1 darwin-amd64) jb@kvar.kastelo.net 2019-05-08 15:38:08 UTC +Panic at 2019-05-16T09:12:45+02:00 +panic: runtime error: invalid memory address or nil pointer dereference +[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x457922a] + +goroutine 171 [running]: +github.com/syncthing/syncthing/lib/connections.(*service).setConnectionStatus(0xc0001a80e0, 0xc001b01020, 0x1a, 0x4b2b0a0, 0xc000021270) + /Users/jb/dev/github.com/syncthing/syncthing/lib/connections/service.go:689 +0x3a +github.com/syncthing/syncthing/lib/connections.(*service).dialParallel.func1(0xc0001a80e0, 0xc0034bf3e0, 0xc003d18510, 0xc001b01020, 0x1a, 0x4b32080, 0xc003d98da0, 0xa, 0xc000b88c80, 0x303a58f8b941897c, ...) + /Users/jb/dev/github.com/syncthing/syncthing/lib/connections/service.go:838 +0xec +created by github.com/syncthing/syncthing/lib/connections.(*service).dialParallel + /Users/jb/dev/github.com/syncthing/syncthing/lib/connections/service.go:836 +0x446 + +goroutine 1 [chan receive]: +main.(*exiter).waitForExit(...) + /Users/jb/dev/github.com/syncthing/syncthing/cmd/syncthing/main.go:289 +main.syncthingMain(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4880b34, 0x1, 0x0, 0x0, ...) + /Users/jb/dev/github.com/syncthing/syncthing/cmd/syncthing/main.go:928 +0x2213 +main.main() + /Users/jb/dev/github.com/syncthing/syncthing/cmd/syncthing/main.go:430 +0x406 + +goroutine 35 [select]: +github.com/syncthing/syncthing/lib/events.(*Logger).Serve(0xc0000c0120) + /Users/jb/dev/github.com/syncthing/syncthing/lib/events/events.go:260 +0x126 +created by github.com/syncthing/syncthing/lib/events.init.1 + /Users/jb/dev/github.com/syncthing/syncthing/lib/events/events.go:234 +0x5b + +goroutine 19 [syscall]: +os/signal.signal_recv(0x0) + /usr/local/go/src/runtime/sigqueue.go:139 +0x9f +os/signal.loop() + /usr/local/go/src/os/signal/signal_unix.go:23 +0x22 +created by os/signal.init.0 + /usr/local/go/src/os/signal/signal_unix.go:29 +0x41 + +goroutine 20 [chan receive]: +github.com/syncthing/notify.(*recursiveTree).dispatch(0xc00015e140) + /Users/jb/go/pkg/mod/github.com/syncthing/notify@v0.0.0-20181107104724-4e389ea6c0d8/tree_recursive.go:125 +0xc7 +created by github.com/syncthing/notify.newRecursiveTree + /Users/jb/go/pkg/mod/github.com/syncthing/notify@v0.0.0-20181107104724-4e389ea6c0d8/tree_recursive.go:119 +0x133 + +goroutine 21 [syscall, locked to thread]: +github.com/syncthing/notify._Cfunc_CFRunLoopRun() + _cgo_gotypes.go:224 +0x41 +github.com/syncthing/notify.init.1.func1() + /Users/jb/go/pkg/mod/github.com/syncthing/notify@v0.0.0-20181107104724-4e389ea6c0d8/watcher_fsevents_cgo.go:72 +0x3c +created by github.com/syncthing/notify.init.1 + /Users/jb/go/pkg/mod/github.com/syncthing/notify@v0.0.0-20181107104724-4e389ea6c0d8/watcher_fsevents_cgo.go:63 +0x4e + +goroutine 39 [chan receive]: +github.com/syncthing/syncthing/lib/discover.(*globalClient).Serve(0xc000246150) + /Users/jb/dev/github.com/syncthing/syncthing/lib/discover/global.go:190 +0x225 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000470f00, 0xc000000002, 0x5788660, 0xc000246150) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 50 [chan receive]: +main.setupSignalHandling.func2(0xc0002205a0) + /Users/jb/dev/github.com/syncthing/syncthing/cmd/syncthing/main.go:959 +0x38 +created by main.setupSignalHandling + /Users/jb/dev/github.com/syncthing/syncthing/cmd/syncthing/main.go:958 +0x160 + +goroutine 26 [chan receive]: +main.setupSignalHandling.func1(0xc000220540) + /Users/jb/dev/github.com/syncthing/syncthing/cmd/syncthing/main.go:949 +0x38 +created by main.setupSignalHandling + /Users/jb/dev/github.com/syncthing/syncthing/cmd/syncthing/main.go:948 +0xb2 + +goroutine 51 [select]: +github.com/thejerf/suture.(*Supervisor).Serve(0xc000268000) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:454 +0x350 +created by github.com/thejerf/suture.(*Supervisor).ServeBackground + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:407 +0x3f + +goroutine 53 [chan receive]: +github.com/syncthing/syncthing/lib/events.(*bufferedSubscription).pollingLoop(0xc000282050) + /Users/jb/dev/github.com/syncthing/syncthing/lib/events/events.go:441 +0x8d +created by github.com/syncthing/syncthing/lib/events.NewBufferedSubscription + /Users/jb/dev/github.com/syncthing/syncthing/lib/events/events.go:436 +0x157 + +goroutine 54 [chan receive]: +github.com/syncthing/syncthing/lib/events.(*bufferedSubscription).pollingLoop(0xc0002820f0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/events/events.go:441 +0x8d +created by github.com/syncthing/syncthing/lib/events.NewBufferedSubscription + /Users/jb/dev/github.com/syncthing/syncthing/lib/events/events.go:436 +0x157 + +goroutine 5 [select]: +github.com/syndtr/goleveldb/leveldb/util.(*BufferPool).drain(0xc0001a8000) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/util/buffer_pool.go:206 +0x121 +created by github.com/syndtr/goleveldb/leveldb/util.NewBufferPool + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/util/buffer_pool.go:237 +0x176 + +goroutine 6 [select]: +github.com/syndtr/goleveldb/leveldb.(*DB).compactionError(0xc0000f8680) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_compaction.go:90 +0xcd +created by github.com/syndtr/goleveldb/leveldb.openDB + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db.go:141 +0x40f + +goroutine 7 [select]: +github.com/syndtr/goleveldb/leveldb.(*DB).mpoolDrain(0xc0000f8680) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_state.go:101 +0xf6 +created by github.com/syndtr/goleveldb/leveldb.openDB + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db.go:142 +0x431 + +goroutine 8 [runnable]: +syscall.syscall(0x40b2bf0, 0x32, 0xc003a12000, 0xf68, 0xf68, 0x0, 0x0) + /usr/local/go/src/runtime/sys_darwin.go:63 +0x2e +syscall.write(0x32, 0xc003a12000, 0xf68, 0x1592, 0x0, 0xc003a12c78, 0x2ec) + /usr/local/go/src/syscall/zsyscall_darwin_amd64.go:1621 +0x67 +syscall.Write(...) + /usr/local/go/src/syscall/syscall_unix.go:191 +internal/poll.(*FD).Write(0xc000081c20, 0xc003a12000, 0xf68, 0x1592, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:268 +0x179 +os.(*File).write(...) + /usr/local/go/src/os/file_unix.go:280 +os.(*File).Write(0xc0036aa768, 0xc003a12000, 0xf68, 0x1592, 0x0, 0x0, 0x0) + /usr/local/go/src/os/file.go:145 +0x76 +github.com/syndtr/goleveldb/leveldb/table.(*Writer).writeBlock(0xc000bd4f00, 0xc000bd4f58, 0x2, 0x80, 0xc000bd5184, 0xc000bd4f58, 0xc000bd1e80) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/table/writer.go:186 +0x1c3 +github.com/syndtr/goleveldb/leveldb/table.(*Writer).finishBlock(0xc000bd4f00, 0xc003e8ca80, 0x79) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/table/writer.go:221 +0x55 +github.com/syndtr/goleveldb/leveldb/table.(*Writer).Append(0xc000bd4f00, 0xc003e8ca80, 0x79, 0x80, 0xc003becf56, 0x300, 0x10a4, 0xc003e8ca80, 0x79) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/table/writer.go:254 +0x2e1 +github.com/syndtr/goleveldb/leveldb.(*tWriter).append(0xc0034bf500, 0xc003e8ca80, 0x79, 0x80, 0xc003becf56, 0x300, 0x10a4, 0xc003e8ca80, 0xc003e8ca80) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/table.go:488 +0xe2 +github.com/syndtr/goleveldb/leveldb.(*tableCompactionBuilder).appendKV(0xc000774960, 0xc003e8ca80, 0x79, 0x80, 0xc003becf56, 0x300, 0x10a4, 0xffffffffffffffff, 0x0) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_compaction.go:396 +0xa3 +github.com/syndtr/goleveldb/leveldb.(*tableCompactionBuilder).run(0xc000774960, 0xc003da5738, 0x0, 0x0) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_compaction.go:514 +0x50b +github.com/syndtr/goleveldb/leveldb.(*DB).compactionTransact(0xc0000f8680, 0x4887dc4, 0xb, 0x4b323c0, 0xc000774960) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_compaction.go:185 +0x161 +github.com/syndtr/goleveldb/leveldb.(*DB).tableCompaction(0xc0000f8680, 0xc000270f00, 0xc000283400) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_compaction.go:577 +0x62b +github.com/syndtr/goleveldb/leveldb.(*DB).tableAutoCompaction(0xc0000f8680) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_compaction.go:633 +0x54 +github.com/syndtr/goleveldb/leveldb.(*DB).tCompaction(0xc0000f8680) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_compaction.go:824 +0x321 +created by github.com/syndtr/goleveldb/leveldb.openDB + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db.go:148 +0x585 + +goroutine 9 [select]: +github.com/syndtr/goleveldb/leveldb.(*DB).mCompaction(0xc0000f8680) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_compaction.go:751 +0x12e +created by github.com/syndtr/goleveldb/leveldb.openDB + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db.go:149 +0x5a7 + +goroutine 27 [sleep]: +runtime.goparkunlock(...) + /usr/local/go/src/runtime/proc.go:307 +time.Sleep(0x45d964b800) + /usr/local/go/src/runtime/time.go:105 +0x159 +github.com/syncthing/syncthing/lib/model.(*deadlockDetector).Watch.func1(0xc0000a0d90, 0x570e6a0, 0xc000146800, 0x48817ae, 0x4) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/util.go:35 +0x58 +created by github.com/syncthing/syncthing/lib/model.(*deadlockDetector).Watch + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/util.go:33 +0xb2 + +goroutine 28 [sleep]: +runtime.goparkunlock(...) + /usr/local/go/src/runtime/proc.go:307 +time.Sleep(0x45d964b800) + /usr/local/go/src/runtime/time.go:105 +0x159 +github.com/syncthing/syncthing/lib/model.(*deadlockDetector).Watch.func1(0xc0000a0d90, 0x570e6a0, 0xc000146820, 0x48819ca, 0x4) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/util.go:35 +0x58 +created by github.com/syncthing/syncthing/lib/model.(*deadlockDetector).Watch + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/util.go:33 +0xb2 + +goroutine 29 [select]: +github.com/thejerf/suture.(*Supervisor).Serve(0xc000470b40) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:454 +0x350 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000268000, 0xc000000000, 0x570e770, 0xc0001a6160) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 30 [select]: +github.com/thejerf/suture.(*Supervisor).Serve(0xc000470f00) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:454 +0x350 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000268000, 0xc000000001, 0x570e7b8, 0xc000020190) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 10 [select]: +github.com/syncthing/syncthing/lib/model.(*ProgressEmitter).Serve(0xc00022e5a0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/progressemitter.go:59 +0x37c +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000470b40, 0xc000000000, 0x4b321c0, 0xc00022e5a0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 11 [chan receive]: +github.com/syncthing/syncthing/lib/model.(*folder).scanSubdirs(0xc00011a840, 0x0, 0x0, 0x0, 0x0, 0x0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/folder.go:402 +0x68f +github.com/syncthing/syncthing/lib/model.(*folder).scanTimerFired(0xc00011a840) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/folder.go:545 +0x54 +github.com/syncthing/syncthing/lib/model.(*folder).Serve(0xc00011a840) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/folder.go:181 +0x7c9 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000470b40, 0xc000000001, 0x570e6c8, 0xc00011a840) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 12 [select]: +github.com/syncthing/syncthing/lib/model.(*folder).Serve(0xc000196840) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/folder.go:153 +0x47d +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000470b40, 0xc000000002, 0x570e6c8, 0xc000196840) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 31 [select]: +github.com/thejerf/suture.(*Supervisor).Serve(0xc000470ff0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:454 +0x350 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000268000, 0xc000000002, 0x4b32040, 0xc0001a80e0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 32 [chan receive]: +github.com/syncthing/syncthing/lib/connections.(*service).dialParallel(0xc0001a80e0, 0x303a58f8b941897c, 0xe0c6153d5b38dadd, 0x6308f7c9a45b6725, 0x9c959a98f78344e6, 0xc0001e50e0, 0x1, 0x1, 0xc00000d567, 0x5, ...) + /Users/jb/dev/github.com/syncthing/syncthing/lib/connections/service.go:854 +0x4c9 +github.com/syncthing/syncthing/lib/connections.(*service).connect(0xc0001a80e0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/connections/service.go:455 +0xee6 +github.com/syncthing/syncthing/lib/connections.serviceFunc.Serve(0xc0000a1010) + /Users/jb/dev/github.com/syncthing/syncthing/lib/connections/structs.go:180 +0x25 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000470ff0, 0xc000000000, 0x4b33700, 0xc0000a1010) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 33 [chan receive]: +github.com/syncthing/syncthing/lib/connections.(*service).handle(0xc0001a80e0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/connections/service.go:193 +0x7d +github.com/syncthing/syncthing/lib/connections.serviceFunc.Serve(0xc0000a1020) + /Users/jb/dev/github.com/syncthing/syncthing/lib/connections/structs.go:180 +0x25 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000470ff0, 0xc000000001, 0x4b33700, 0xc0000a1020) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 66 [select]: +github.com/thejerf/suture.(*Supervisor).Serve(0xc0004710e0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:454 +0x350 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000470ff0, 0xc000000002, 0x4b32400, 0xc0004710e0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 67 [IO wait]: +internal/poll.runtime_pollWait(0x5740f08, 0x72, 0x0) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc0002cc518, 0x72, 0x0, 0x0, 0x4882e05) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).Accept(0xc0002cc500, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:384 +0x1ba +net.(*netFD).accept(0xc0002cc500, 0x460f4bb75024, 0x3b9ac39a, 0xc000065ac8) + /usr/local/go/src/net/fd_unix.go:238 +0x42 +net.(*TCPListener).accept(0xc0000be0e0, 0xe9, 0x0, 0x0) + /usr/local/go/src/net/tcpsock_posix.go:139 +0x32 +net.(*TCPListener).Accept(0xc0000be0e0, 0xbf2f613b6ecc3d68, 0xe8b29287, 0x50bfa40, 0x0) + /usr/local/go/src/net/tcpsock.go:260 +0x48 +github.com/syncthing/syncthing/lib/connections.(*tcpListener).Serve(0xc00017a1b0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/connections/tcp_listen.go:87 +0x728 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc0004710e0, 0xc000000000, 0x570e8a0, 0xc00017a1b0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 57 [select]: +github.com/syncthing/syncthing/lib/discover.(*globalClient).Serve(0xc00015c3f0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/discover/global.go:201 +0x177 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000470f00, 0xc000000000, 0x5788660, 0xc00015c3f0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 58 [select]: +github.com/syncthing/syncthing/lib/discover.(*globalClient).Serve(0xc00015c460) + /Users/jb/dev/github.com/syncthing/syncthing/lib/discover/global.go:201 +0x177 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000470f00, 0xc000000001, 0x5788660, 0xc00015c460) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 114 [chan receive]: +github.com/rcrowley/go-metrics.(*meterArbiter).tick(0x50bf5c0) + /Users/jb/go/pkg/mod/github.com/rcrowley/go-metrics@v0.0.0-20171128170426-e181e095bae9/meter.go:252 +0x31 +created by github.com/rcrowley/go-metrics.NewMeter + /Users/jb/go/pkg/mod/github.com/rcrowley/go-metrics@v0.0.0-20171128170426-e181e095bae9/meter.go:44 +0x107 + +goroutine 40 [chan receive]: +github.com/syncthing/syncthing/lib/beacon.(*Broadcast).Recv(0xc0000cbda0, 0xc00016c1b8, 0x20, 0xc00046ee01, 0x2, 0x2) + /Users/jb/dev/github.com/syncthing/syncthing/lib/beacon/broadcast.go:67 +0x53 +github.com/syncthing/syncthing/lib/discover.(*localClient).recvAnnouncements(0xc00016c1b0, 0x4b3d600, 0xc0000cbda0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/discover/local.go:164 +0xb1 +created by github.com/syncthing/syncthing/lib/discover.(*localClient).startLocalIPv4Broadcasts + /Users/jb/dev/github.com/syncthing/syncthing/lib/discover/local.go:89 +0xd5 + +goroutine 41 [select]: +github.com/syncthing/syncthing/lib/discover.(*localClient).sendLocalAnnouncements(0xc00016c1b0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/discover/local.go:154 +0x123 +created by github.com/syncthing/syncthing/lib/discover.NewLocal + /Users/jb/dev/github.com/syncthing/syncthing/lib/discover/local.go:81 +0x2d9 + +goroutine 42 [select]: +github.com/thejerf/suture.(*Supervisor).Serve(0xc000268e10) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:454 +0x350 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000470f00, 0xc000000003, 0x5741588, 0xc00016c1b0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 43 [chan receive]: +github.com/syncthing/syncthing/lib/beacon.(*Multicast).Recv(0xc0000cbf20, 0xc00016c3f8, 0x20, 0xc0000acb01, 0x2, 0x2) + /Users/jb/dev/github.com/syncthing/syncthing/lib/beacon/multicast.go:67 +0x53 +github.com/syncthing/syncthing/lib/discover.(*localClient).recvAnnouncements(0xc00016c3f0, 0x4b3d640, 0xc0000cbf20) + /Users/jb/dev/github.com/syncthing/syncthing/lib/discover/local.go:164 +0xb1 +created by github.com/syncthing/syncthing/lib/discover.(*localClient).startLocalIPv6Multicasts + /Users/jb/dev/github.com/syncthing/syncthing/lib/discover/local.go:95 +0xdf + +goroutine 44 [select]: +github.com/syncthing/syncthing/lib/discover.(*localClient).sendLocalAnnouncements(0xc00016c3f0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/discover/local.go:154 +0x123 +created by github.com/syncthing/syncthing/lib/discover.NewLocal + /Users/jb/dev/github.com/syncthing/syncthing/lib/discover/local.go:81 +0x2d9 + +goroutine 45 [select]: +github.com/thejerf/suture.(*Supervisor).Serve(0xc000268ff0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:454 +0x350 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000470f00, 0xc000000004, 0x5741588, 0xc00016c3f0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 46 [select]: +github.com/syncthing/syncthing/lib/ur.(*Service).Serve(0xc0002461c0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/ur/usage_report.go:399 +0x231 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000268000, 0xc000000003, 0x4b32340, 0xc0002461c0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 47 [select]: +main.(*cpuService).Serve(0xc0000ce860) + /Users/jb/dev/github.com/syncthing/syncthing/cmd/syncthing/cpuusage.go:41 +0x170 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000268000, 0xc000000004, 0x4b32780, 0xc0000ce860) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 14 [runnable]: +syscall.syscall(0x40b2ca0, 0x33, 0xc00353d978, 0x0, 0x0, 0x0, 0x0) + /usr/local/go/src/runtime/sys_darwin.go:63 +0x2e +syscall.Fstat(0x33, 0xc00353d978, 0xc00353d980, 0x4037cbe) + /usr/local/go/src/syscall/zsyscall_darwin_amd64.go:1823 +0x62 +os.newFile(0x33, 0xc0000b2510, 0x2e, 0x1, 0x33) + /usr/local/go/src/os/file_unix.go:150 +0x1f5 +os.openFileNolog(0xc0000b2510, 0x2e, 0x0, 0xc0000001ff, 0x12, 0xc000537e20, 0x1b) + /usr/local/go/src/os/file_unix.go:227 +0x1f9 +os.OpenFile(0xc0000b2510, 0x2e, 0x0, 0x1ff, 0xc0000b2510, 0x2e, 0x0) + /usr/local/go/src/os/file.go:284 +0x5f +github.com/syncthing/syncthing/lib/fs.(*BasicFilesystem).DirNames(0xc0000c3b70, 0xc000537e20, 0x1b, 0x0, 0x0, 0x0, 0x0, 0x0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/fs/basicfs.go:195 +0xa5 +github.com/syncthing/syncthing/lib/fs.(*walkFilesystem).walk(0xc0000c3b80, 0xc000537e20, 0x1b, 0x4b43d80, 0xc0014cf1b0, 0xc0001e4280, 0x0, 0x0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/fs/walkfs.go:58 +0x1d7 +github.com/syncthing/syncthing/lib/fs.(*walkFilesystem).walk(0xc0000c3b80, 0xc0038b2f40, 0x16, 0x4b43d80, 0xc0011f6940, 0xc0001e4280, 0x0, 0x0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/fs/walkfs.go:71 +0x41e +github.com/syncthing/syncthing/lib/fs.(*walkFilesystem).walk(0xc0000c3b80, 0xc003dfd320, 0x14, 0x4b43d80, 0xc001016050, 0xc0001e4280, 0x0, 0x0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/fs/walkfs.go:71 +0x41e +github.com/syncthing/syncthing/lib/fs.(*walkFilesystem).walk(0xc0000c3b80, 0x4880b35, 0x1, 0x4b43d80, 0xc0000c3e30, 0xc0001e4280, 0x0, 0xc000237f48) + /Users/jb/dev/github.com/syncthing/syncthing/lib/fs/walkfs.go:71 +0x41e +github.com/syncthing/syncthing/lib/fs.(*walkFilesystem).Walk(0xc0000c3b80, 0x4880b35, 0x1, 0xc0001e4280, 0x50bfa40, 0xc0000c3d70) + /Users/jb/dev/github.com/syncthing/syncthing/lib/fs/walkfs.go:93 +0xd3 +github.com/syncthing/syncthing/lib/scanner.(*walker).walk.func1(0xc00014e080, 0x4b3b4c0, 0xc0000b6cc0, 0xc00026afc0, 0xc00026b020) + /Users/jb/dev/github.com/syncthing/syncthing/lib/scanner/walk.go:111 +0x127 +created by github.com/syncthing/syncthing/lib/scanner.(*walker).walk + /Users/jb/dev/github.com/syncthing/syncthing/lib/scanner/walk.go:108 +0x18c + +goroutine 15 [chan receive]: +github.com/syncthing/syncthing/lib/scanner.(*walker).walk.func2(0xc00026afc0, 0x4b3b4c0, 0xc0000b6cc0, 0xc00014e080, 0xc00026b020, 0xc0001e4230) + /Users/jb/dev/github.com/syncthing/syncthing/lib/scanner/walk.go:145 +0xb3 +created by github.com/syncthing/syncthing/lib/scanner.(*walker).walk + /Users/jb/dev/github.com/syncthing/syncthing/lib/scanner/walk.go:141 +0x216 + +goroutine 48 [select]: +github.com/thejerf/suture.(*Supervisor).Serve(0xc0002691d0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:454 +0x350 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000268000, 0xc000000005, 0x5741778, 0xc0000f2960) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 16 [select]: +github.com/thejerf/suture.(*Supervisor).Serve(0xc0002690e0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:454 +0x350 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000268ff0, 0xc000000000, 0x5741610, 0xc0000cbf20) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 82 [IO wait]: +internal/poll.runtime_pollWait(0x5740e38, 0x72, 0xc002ef2070) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc00014e118, 0x72, 0xc00014e100, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).RawRead(0xc00014e100, 0xc00030aab0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:534 +0x100 +net.(*rawConn).Read(0xc000266068, 0xc00030aab0, 0x1, 0x1) + /usr/local/go/src/net/rawconn.go:43 +0x57 +golang.org/x/net/internal/socket.(*Conn).recvMsg(0xc0000ac7e0, 0xc0003a7cb8, 0x0, 0x0, 0xc000010ae0) + /Users/jb/go/pkg/mod/golang.org/x/net@v0.0.0-20181201002055-351d144fa1fc/internal/socket/rawconn_msg.go:32 +0x20e +golang.org/x/net/internal/socket.(*Conn).RecvMsg(...) + /Users/jb/go/pkg/mod/golang.org/x/net@v0.0.0-20181201002055-351d144fa1fc/internal/socket/socket.go:252 +golang.org/x/net/ipv6.(*payloadHandler).readFrom(0xc00015e560, 0xc002e76000, 0x10000, 0x10000, 0x4008184, 0xc0000c1980, 0xc0003a7e90, 0x4765000, 0x4557c0f, 0xc000116601) + /Users/jb/go/pkg/mod/golang.org/x/net@v0.0.0-20181201002055-351d144fa1fc/ipv6/payload_cmsg_go1_9.go:25 +0x1a7 +golang.org/x/net/ipv6.(*payloadHandler).ReadFrom(0xc00015e560, 0xc002e76000, 0x10000, 0x10000, 0x2, 0x2, 0x4b32940, 0xc00030aa50, 0x0, 0x0) + /Users/jb/go/pkg/mod/golang.org/x/net@v0.0.0-20181201002055-351d144fa1fc/ipv6/payload_cmsg.go:19 +0x6d +github.com/syncthing/syncthing/lib/beacon.(*multicastReader).Serve(0xc00007d600) + /Users/jb/dev/github.com/syncthing/syncthing/lib/beacon/multicast.go:204 +0x760 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc0002690e0, 0xc000000000, 0x4b31f00, 0xc00007d600) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 83 [chan receive]: +github.com/syncthing/syncthing/lib/beacon.(*multicastWriter).Serve(0xc00007d640) + /Users/jb/dev/github.com/syncthing/syncthing/lib/beacon/multicast.go:109 +0x849 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc0002690e0, 0xc000000001, 0x4b31f40, 0xc00007d640) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 103 [runnable]: +syscall.syscall6(0x40b2b00, 0x27, 0xc0034c6800, 0x28d, 0x1ec396, 0x0, 0x0, 0x28d, 0x0, 0x0) + /usr/local/go/src/runtime/sys_darwin.go:74 +0x2e +syscall.Pread(0x27, 0xc0034c6800, 0x28d, 0x3df, 0x1ec396, 0x18, 0xc0012a6488, 0x402e891) + /usr/local/go/src/syscall/zsyscall_darwin_amd64.go:1127 +0x7f +internal/poll.(*FD).Pread(0xc0031e7200, 0xc0034c6800, 0x28d, 0x3df, 0x1ec396, 0xc0000bc2a0, 0x1, 0x4a46f28) + /usr/local/go/src/internal/poll/fd_unix.go:196 +0xa2 +os.(*File).pread(...) + /usr/local/go/src/os/file_unix.go:272 +os.(*File).ReadAt(0xc000fa23e0, 0xc0034c6800, 0x28d, 0x3df, 0x1ec396, 0x0, 0x0, 0x0) + /usr/local/go/src/os/file.go:126 +0x103 +github.com/syndtr/goleveldb/leveldb/table.(*Reader).readRawBlock(0xc0001e9790, 0x1ec396, 0x288, 0x4847c01, 0x203001, 0xc000ab10a0, 0xc0012a6750, 0x4597d8d, 0xc003f38690) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/table/reader.go:564 +0xb2 +github.com/syndtr/goleveldb/leveldb/table.(*Reader).readBlock(0xc0001e9790, 0x1ec396, 0x288, 0x1, 0x8, 0xc0035a4b40, 0xc000fc4000) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/table/reader.go:603 +0x55 +github.com/syndtr/goleveldb/leveldb/table.(*Reader).readBlockCached.func1(0xc000ab10c0, 0xc0000b6280, 0xc003830480) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/table/reader.go:627 +0x51 +github.com/syndtr/goleveldb/leveldb/cache.(*Cache).Get(0xc0000b6280, 0x1eb91, 0x1ec396, 0xc000fc4000, 0x0) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/cache/cache.go:389 +0x1d7 +github.com/syndtr/goleveldb/leveldb/cache.(*NamespaceGetter).Get(...) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/cache/cache.go:58 +github.com/syndtr/goleveldb/leveldb/table.(*Reader).readBlockCached(0xc0001e9790, 0x1ec396, 0x288, 0x4590101, 0xc000248400, 0xc0012a6880, 0x402dfef, 0x8, 0xc0000c99c0) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/table/reader.go:625 +0x158 +github.com/syndtr/goleveldb/leveldb/table.(*Reader).getDataIter(0xc0001e9790, 0x1ec396, 0x288, 0x0, 0x101, 0x288, 0x2) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/table/reader.go:765 +0x5b +github.com/syndtr/goleveldb/leveldb/table.(*Reader).getDataIterErr(0xc0001e9790, 0x1ec396, 0x288, 0x0, 0x101, 0x0, 0x0) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/table/reader.go:780 +0x12e +github.com/syndtr/goleveldb/leveldb/table.(*indexIter).Get(0xc000aa7720, 0x459fa94, 0xc000248400) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/table/reader.go:507 +0x2b6 +github.com/syndtr/goleveldb/leveldb/iterator.(*indexedIterator).setData(0xc0031e72c0) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/iterator/indexed_iter.go:39 +0x41 +github.com/syndtr/goleveldb/leveldb/iterator.(*indexedIterator).Next(0xc0031e72c0, 0x20) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/iterator/indexed_iter.go:160 +0xb6 +github.com/syndtr/goleveldb/leveldb/iterator.(*indexedIterator).Next(0xc0031e7080, 0x20) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/iterator/indexed_iter.go:149 +0x17e +github.com/syndtr/goleveldb/leveldb/iterator.(*mergedIterator).Next(0xc00014cc80, 0x0) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/iterator/merged_iter.go:169 +0xe2 +github.com/syndtr/goleveldb/leveldb.(*dbIter).Next(0xc00016c510, 0x1) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_iter.go:240 +0x97 +github.com/syncthing/syncthing/lib/db.(*instance).withNeed(0xc00046e1e0, 0xc0004be9e0, 0xb, 0x10, 0xc0012a6da0, 0x20, 0x20, 0x1, 0xc0004bd400) + /Users/jb/dev/github.com/syncthing/syncthing/lib/db/instance.go:331 +0x2b6 +github.com/syncthing/syncthing/lib/db.(*FileSet).WithNeedTruncated(0xc0000b6b00, 0x303a58f8b941897c, 0xe0c6153d5b38dadd, 0x6308f7c9a45b6725, 0x9c959a98f78344e6, 0xc003338740) + /Users/jb/dev/github.com/syncthing/syncthing/lib/db/set.go:162 +0x1ee +github.com/syncthing/syncthing/lib/model.(*model).Completion(0xc0001a6160, 0x303a58f8b941897c, 0xe0c6153d5b38dadd, 0x6308f7c9a45b6725, 0x9c959a98f78344e6, 0xc0002482e6, 0xb, 0x0, 0x0, 0x0, ...) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/model.go:693 +0x34a +github.com/syncthing/syncthing/lib/api.(*service).getDBCompletion(0xc000118dc0, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:654 +0x13e +net/http.HandlerFunc.ServeHTTP(0xc002ef2080, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.(*ServeMux).ServeHTTP(0xc00022a880, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:2375 +0x1d6 +github.com/syncthing/syncthing/lib/api.getPostHandler.func1(0x4b39580, 0xc001116380, 0xc003ce0d00) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:426 +0xe6 +net/http.HandlerFunc.ServeHTTP(0xc00030abd0, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.metricsMiddleware.func1(0x4b39580, 0xc001116380, 0xc003ce0d00) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:518 +0x117 +net/http.HandlerFunc.ServeHTTP(0xc000010bc0, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.noCacheMiddleware.func1(0x4b39580, 0xc001116380, 0xc003ce0d00) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:541 +0x3f4 +net/http.HandlerFunc.ServeHTTP(0xc000010be0, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.(*ServeMux).ServeHTTP(0xc00022a940, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:2375 +0x1d6 +github.com/syncthing/syncthing/lib/api.csrfMiddleware.func1(0x4b39580, 0xc001116380, 0xc003ce0d00) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api_csrf.go:78 +0x208 +net/http.HandlerFunc.ServeHTTP(0xc0001713f0, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.withDetailsMiddleware.func1(0x4b39580, 0xc001116380, 0xc003ce0d00) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:549 +0x2ce +net/http.HandlerFunc.ServeHTTP(0xc0000c94c0, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.basicAuthAndSessionMiddleware.func1(0x4b39580, 0xc001116380, 0xc003ce0d00) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api_auth.go:51 +0xa64 +net/http.HandlerFunc.ServeHTTP(0xc0001e9040, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.redirectToHTTPSMiddleware.func1(0x4b39580, 0xc001116380, 0xc003ce0d00) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:531 +0x117 +net/http.HandlerFunc.ServeHTTP(0xc0000ad700, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.corsMiddleware.func1(0x4b39580, 0xc001116380, 0xc003ce0d00) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:510 +0x2a6 +net/http.HandlerFunc.ServeHTTP(0xc0000ad720, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.debugMiddleware.func1(0x4b39580, 0xc001116380, 0xc003ce0d00) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:438 +0xa7 +net/http.HandlerFunc.ServeHTTP(0xc0000ad740, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.serverHandler.ServeHTTP(0xc0001e9110, 0x4b39580, 0xc001116380, 0xc003ce0d00) + /usr/local/go/src/net/http/server.go:2774 +0xa8 +net/http.(*conn).serve(0xc0013546e0, 0x4b3b4c0, 0xc000ea0000) + /usr/local/go/src/net/http/server.go:1878 +0x851 +created by net/http.(*Server).Serve + /usr/local/go/src/net/http/server.go:2884 +0x2f4 + +goroutine 139 [IO wait]: +internal/poll.runtime_pollWait(0x57402d8, 0x72, 0xffffffffffffffff) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc001002718, 0x72, 0x600, 0x62b, 0xffffffffffffffff) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).Read(0xc001002700, 0xc00035f100, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:169 +0x1f2 +net.(*netFD).Read(0xc001002700, 0xc00035f100, 0x62b, 0x62b, 0xc003f3b8c0, 0x8, 0x4a46af0) + /usr/local/go/src/net/fd_unix.go:202 +0x4f +net.(*conn).Read(0xc001199ae0, 0xc00035f100, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/net/net.go:177 +0x69 +github.com/syncthing/syncthing/lib/tlsutil.(*UnionedConnection).Read(0xc00138c8a0, 0xc00035f100, 0x62b, 0x62b, 0xc003f3b900, 0xc003f3b9a8, 0x10) + /Users/jb/dev/github.com/syncthing/syncthing/lib/tlsutil/tlsutil.go:223 +0xc1 +crypto/tls.(*atLeastReader).Read(0xc000239200, 0xc00035f100, 0x62b, 0x62b, 0xc00409a005, 0xc001002718, 0xc003f3b9d8) + /usr/local/go/src/crypto/tls/conn.go:761 +0x60 +bytes.(*Buffer).ReadFrom(0xc000036958, 0x4b2a4a0, 0xc000239200, 0x400bc55, 0x47b4f40, 0x4812c80) + /usr/local/go/src/bytes/buffer.go:207 +0xbd +crypto/tls.(*Conn).readFromUntil(0xc000036700, 0x572adf0, 0xc00138c8a0, 0x5, 0xc00138c8a0, 0x1e0) + /usr/local/go/src/crypto/tls/conn.go:783 +0xf8 +crypto/tls.(*Conn).readRecordOrCCS(0xc000036700, 0x4a46f00, 0xc000036838, 0x431b6ba) + /usr/local/go/src/crypto/tls/conn.go:590 +0x125 +crypto/tls.(*Conn).readRecord(...) + /usr/local/go/src/crypto/tls/conn.go:558 +crypto/tls.(*Conn).Read(0xc000036700, 0xc000b31000, 0x1000, 0x1000, 0x0, 0x0, 0x0) + /usr/local/go/src/crypto/tls/conn.go:1236 +0x137 +net/http.(*connReader).Read(0xc00375e3f0, 0xc000b31000, 0x1000, 0x1000, 0x425ea21, 0xc00138c8a0, 0xbf2f613ef969b548) + /usr/local/go/src/net/http/server.go:787 +0x107 +bufio.(*Reader).fill(0xc0007eec00) + /usr/local/go/src/bufio/bufio.go:100 +0x10f +bufio.(*Reader).Peek(0xc0007eec00, 0x4, 0x435c71b54, 0x50bfa40, 0x0, 0x0, 0x50bfa40) + /usr/local/go/src/bufio/bufio.go:138 +0x4f +net/http.(*conn).serve(0xc0013545a0, 0x4b3b4c0, 0xc001778f00) + /usr/local/go/src/net/http/server.go:1903 +0x9bf +created by net/http.(*Server).Serve + /usr/local/go/src/net/http/server.go:2884 +0x2f4 + +goroutine 86 [select]: +github.com/syncthing/syncthing/lib/fs.(*BasicFilesystem).watchLoop(0xc0000c3b70, 0x4880b35, 0x1, 0xc0000383c0, 0x12, 0xc0000bd320, 0xc00026b140, 0x4b32140, 0xc00017a090, 0x4b3b4c0, ...) + /Users/jb/dev/github.com/syncthing/syncthing/lib/fs/basicfs_watch.go:81 +0x2c8 +created by github.com/syncthing/syncthing/lib/fs.(*BasicFilesystem).Watch + /Users/jb/dev/github.com/syncthing/syncthing/lib/fs/basicfs_watch.go:59 +0x3e7 + +goroutine 72 [select]: +github.com/thejerf/suture.(*Supervisor).Serve(0xc000268f00) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:454 +0x350 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000268e10, 0xc000000000, 0x5741508, 0xc0000cbda0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 73 [IO wait]: +internal/poll.runtime_pollWait(0x5740bc8, 0x72, 0x0) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc00014e198, 0x72, 0x10000, 0x10000, 0x0) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).ReadFrom(0xc00014e180, 0xc002d06000, 0x10000, 0x10000, 0x0, 0x0, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:219 +0x194 +net.(*netFD).readFrom(0xc00014e180, 0xc002d06000, 0x10000, 0x10000, 0x4, 0xc00044df40, 0xc0000d3500, 0xc00044de50, 0x400725c) + /usr/local/go/src/net/fd_unix.go:208 +0x5b +net.(*UDPConn).readFrom(0xc0000be100, 0xc002d06000, 0x10000, 0x10000, 0xc0000c18c0, 0xc00044de88, 0x4008184, 0xc0000c18c0) + /usr/local/go/src/net/udpsock_posix.go:47 +0x6a +net.(*UDPConn).ReadFrom(0xc0000be100, 0xc002d06000, 0x10000, 0x10000, 0x2, 0x2, 0xc0001e74a0, 0x0, 0x0) + /usr/local/go/src/net/udpsock.go:121 +0x5e +github.com/syncthing/syncthing/lib/beacon.(*broadcastReader).Serve(0xc00007d540) + /Users/jb/dev/github.com/syncthing/syncthing/lib/beacon/broadcast.go:196 +0x371 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000268f00, 0xc000000000, 0x4b31e80, 0xc00007d540) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 74 [chan receive]: +github.com/syncthing/syncthing/lib/beacon.(*broadcastWriter).Serve(0xc00007d580) + /Users/jb/dev/github.com/syncthing/syncthing/lib/beacon/broadcast.go:102 +0x3ca +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000268f00, 0xc000000001, 0x4b31ec0, 0xc00007d580) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 140 [IO wait]: +internal/poll.runtime_pollWait(0x5740208, 0x72, 0xffffffffffffffff) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc000b88418, 0x72, 0x600, 0x62b, 0xffffffffffffffff) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).Read(0xc000b88400, 0xc00035e300, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:169 +0x1f2 +net.(*netFD).Read(0xc000b88400, 0xc00035e300, 0x62b, 0x62b, 0xc003f3d8c0, 0x8, 0xc000242f00) + /usr/local/go/src/net/fd_unix.go:202 +0x4f +net.(*conn).Read(0xc000fa3568, 0xc00035e300, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/net/net.go:177 +0x69 +github.com/syncthing/syncthing/lib/tlsutil.(*UnionedConnection).Read(0xc00138ce60, 0xc00035e300, 0x62b, 0x62b, 0xc003f3d900, 0xc003f3d9a8, 0x10) + /Users/jb/dev/github.com/syncthing/syncthing/lib/tlsutil/tlsutil.go:223 +0xc1 +crypto/tls.(*atLeastReader).Read(0xc003301b00, 0xc00035e300, 0x62b, 0x62b, 0xc00337e1e5, 0xc000b88418, 0xc003f3d9d8) + /usr/local/go/src/crypto/tls/conn.go:761 +0x60 +bytes.(*Buffer).ReadFrom(0xc000037058, 0x4b2a4a0, 0xc003301b00, 0x400bc55, 0x47b4f40, 0x4812c80) + /usr/local/go/src/bytes/buffer.go:207 +0xbd +crypto/tls.(*Conn).readFromUntil(0xc000036e00, 0x572adf0, 0xc00138ce60, 0x5, 0xc00138ce60, 0x1e0) + /usr/local/go/src/crypto/tls/conn.go:783 +0xf8 +crypto/tls.(*Conn).readRecordOrCCS(0xc000036e00, 0x4a46f00, 0xc000036f38, 0x431b6ba) + /usr/local/go/src/crypto/tls/conn.go:590 +0x125 +crypto/tls.(*Conn).readRecord(...) + /usr/local/go/src/crypto/tls/conn.go:558 +crypto/tls.(*Conn).Read(0xc000036e00, 0xc001b79000, 0x1000, 0x1000, 0x0, 0x0, 0x0) + /usr/local/go/src/crypto/tls/conn.go:1236 +0x137 +net/http.(*connReader).Read(0xc000ab8360, 0xc001b79000, 0x1000, 0x1000, 0x425ea21, 0xc00138ce60, 0xbf2f613ef99ccb68) + /usr/local/go/src/net/http/server.go:787 +0x107 +bufio.(*Reader).fill(0xc000fcc300) + /usr/local/go/src/bufio/bufio.go:100 +0x10f +bufio.(*Reader).Peek(0xc000fcc300, 0x4, 0x435fa3146, 0x50bfa40, 0x0, 0x0, 0x50bfa40) + /usr/local/go/src/bufio/bufio.go:138 +0x4f +net/http.(*conn).serve(0xc001354640, 0x4b3b4c0, 0xc0013bfec0) + /usr/local/go/src/net/http/server.go:1903 +0x9bf +created by net/http.(*Server).Serve + /usr/local/go/src/net/http/server.go:2884 +0x2f4 + +goroutine 79 [sleep]: +runtime.goparkunlock(...) + /usr/local/go/src/runtime/proc.go:307 +time.Sleep(0x2540be400) + /usr/local/go/src/runtime/time.go:105 +0x159 +main.standbyMonitor() + /Users/jb/dev/github.com/syncthing/syncthing/cmd/syncthing/main.go:1154 +0x6b +created by main.syncthingMain + /Users/jb/dev/github.com/syncthing/syncthing/cmd/syncthing/main.go:884 +0x2608 + +goroutine 63 [IO wait]: +internal/poll.runtime_pollWait(0x5740af8, 0x72, 0xffffffffffffffff) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc00014e218, 0x72, 0x600, 0x611, 0xffffffffffffffff) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).Read(0xc00014e200, 0xc0036e9500, 0x611, 0x611, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:169 +0x1f2 +net.(*netFD).Read(0xc00014e200, 0xc0036e9500, 0x611, 0x611, 0x203000, 0x411558d, 0xc0005b00a5) + /usr/local/go/src/net/fd_unix.go:202 +0x4f +net.(*conn).Read(0xc0000126e0, 0xc0036e9500, 0x611, 0x611, 0x0, 0x0, 0x0) + /usr/local/go/src/net/net.go:177 +0x69 +crypto/tls.(*atLeastReader).Read(0xc0000ced60, 0xc0036e9500, 0x611, 0x611, 0x42af5ef, 0xc003717140, 0xc00044c938) + /usr/local/go/src/crypto/tls/conn.go:761 +0x60 +bytes.(*Buffer).ReadFrom(0xc0000365d8, 0x4b2a4a0, 0xc0000ced60, 0x400bc55, 0x47b4f40, 0x4852500) + /usr/local/go/src/bytes/buffer.go:207 +0xbd +crypto/tls.(*Conn).readFromUntil(0xc000036380, 0x5712c90, 0xc0000126e0, 0x5, 0xc0000126e0, 0x203000) + /usr/local/go/src/crypto/tls/conn.go:783 +0xf8 +crypto/tls.(*Conn).readRecordOrCCS(0xc000036380, 0x4a46f00, 0xc0000364b8, 0xc00044cdd0) + /usr/local/go/src/crypto/tls/conn.go:590 +0x125 +crypto/tls.(*Conn).readRecord(...) + /usr/local/go/src/crypto/tls/conn.go:558 +crypto/tls.(*Conn).Read(0xc000036380, 0xc0005b0000, 0x1000, 0x1000, 0x0, 0x0, 0x0) + /usr/local/go/src/crypto/tls/conn.go:1236 +0x137 +net/http.(*persistConn).Read(0xc0000d0b40, 0xc0005b0000, 0x1000, 0x1000, 0x405bd50, 0xc00044ce88, 0x2) + /usr/local/go/src/net/http/transport.go:1524 +0x7b +bufio.(*Reader).fill(0xc003717140) + /usr/local/go/src/bufio/bufio.go:100 +0x10f +bufio.(*Reader).Peek(0xc003717140, 0x1, 0x2, 0x0, 0x0, 0xc003ef3800, 0x0) + /usr/local/go/src/bufio/bufio.go:138 +0x4f +net/http.(*persistConn).readLoop(0xc0000d0b40) + /usr/local/go/src/net/http/transport.go:1677 +0x1a3 +created by net/http.(*Transport).dialConn + /usr/local/go/src/net/http/transport.go:1357 +0xae8 + +goroutine 130 [select]: +github.com/syncthing/syncthing/lib/sync.(*TimeoutCondWaiter).Wait(0xc001200e58, 0x4a45d00) + /Users/jb/dev/github.com/syncthing/syncthing/lib/sync/sync.go:292 +0x115 +github.com/syncthing/syncthing/lib/events.(*bufferedSubscription).Since(0xc0002820f0, 0x0, 0x50e2748, 0x0, 0x0, 0xdf8475800, 0x0, 0x0, 0x0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/events/events.go:461 +0x4db +github.com/syncthing/syncthing/lib/api.(*service).getEvents(0xc000118dc0, 0x4b39580, 0xc0014cc2a0, 0xc00013a700, 0x4b2a820, 0xc0002820f0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:1191 +0x2a4 +github.com/syncthing/syncthing/lib/api.(*service).getDiskEvents(0xc000118dc0, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:1167 +0x74 +net/http.HandlerFunc.ServeHTTP(0xc002ef2140, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.(*ServeMux).ServeHTTP(0xc00022a880, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:2375 +0x1d6 +github.com/syncthing/syncthing/lib/api.getPostHandler.func1(0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:426 +0xe6 +net/http.HandlerFunc.ServeHTTP(0xc00030abd0, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.metricsMiddleware.func1(0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:518 +0x117 +net/http.HandlerFunc.ServeHTTP(0xc000010bc0, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.noCacheMiddleware.func1(0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:541 +0x3f4 +net/http.HandlerFunc.ServeHTTP(0xc000010be0, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.(*ServeMux).ServeHTTP(0xc00022a940, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:2375 +0x1d6 +github.com/syncthing/syncthing/lib/api.csrfMiddleware.func1(0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api_csrf.go:78 +0x208 +net/http.HandlerFunc.ServeHTTP(0xc0001713f0, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.withDetailsMiddleware.func1(0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:549 +0x2ce +net/http.HandlerFunc.ServeHTTP(0xc0000c94c0, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.basicAuthAndSessionMiddleware.func1(0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api_auth.go:51 +0xa64 +net/http.HandlerFunc.ServeHTTP(0xc0001e9040, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.redirectToHTTPSMiddleware.func1(0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:531 +0x117 +net/http.HandlerFunc.ServeHTTP(0xc0000ad700, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.corsMiddleware.func1(0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:510 +0x2a6 +net/http.HandlerFunc.ServeHTTP(0xc0000ad720, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.debugMiddleware.func1(0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:438 +0xa7 +net/http.HandlerFunc.ServeHTTP(0xc0000ad740, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.serverHandler.ServeHTTP(0xc0001e9110, 0x4b39580, 0xc0014cc2a0, 0xc00013a700) + /usr/local/go/src/net/http/server.go:2774 +0xa8 +net/http.(*conn).serve(0xc0010ac5a0, 0x4b3b4c0, 0xc00330e000) + /usr/local/go/src/net/http/server.go:1878 +0x851 +created by net/http.(*Server).Serve + /usr/local/go/src/net/http/server.go:2884 +0x2f4 + +goroutine 92 [runnable]: +github.com/syndtr/goleveldb/leveldb/iterator.(*indexedIterator).Value(0xc0031e6060, 0x2e, 0x80, 0x1) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/iterator/indexed_iter.go:205 +0x81 +github.com/syndtr/goleveldb/leveldb/iterator.(*mergedIterator).Value(0xc00014c680, 0xc00322ca80, 0x2e, 0x40) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/iterator/merged_iter.go:251 +0x74 +github.com/syndtr/goleveldb/leveldb.(*dbIter).next(0xc0002502d0, 0x1) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_iter.go:213 +0x330 +github.com/syndtr/goleveldb/leveldb.(*dbIter).Next(0xc0002502d0, 0x1) + /Users/jb/go/pkg/mod/github.com/syndtr/goleveldb@v0.0.0-20171214120811-34011bf325bc/leveldb/db_iter.go:245 +0xd9 +github.com/syncthing/syncthing/lib/db.(*instance).withNeed(0xc00046e1e0, 0xc000953c10, 0xb, 0x10, 0xc0012a2da0, 0x20, 0x20, 0x1, 0xc003492290) + /Users/jb/dev/github.com/syncthing/syncthing/lib/db/instance.go:331 +0x2b6 +github.com/syncthing/syncthing/lib/db.(*FileSet).WithNeedTruncated(0xc0000b6b00, 0x5d4a557355ee1a96, 0x95ccd59f7d44241, 0x23a9c69bae83ac87, 0x6ee52bc80a137f7b, 0xc00133c280) + /Users/jb/dev/github.com/syncthing/syncthing/lib/db/set.go:162 +0x1ee +github.com/syncthing/syncthing/lib/model.(*model).Completion(0xc0001a6160, 0x5d4a557355ee1a96, 0x95ccd59f7d44241, 0x23a9c69bae83ac87, 0x6ee52bc80a137f7b, 0xc000cd6ae6, 0xb, 0x0, 0x0, 0x0, ...) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/model.go:693 +0x34a +github.com/syncthing/syncthing/lib/api.(*service).getDBCompletion(0xc000118dc0, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:654 +0x13e +net/http.HandlerFunc.ServeHTTP(0xc002ef2080, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.(*ServeMux).ServeHTTP(0xc00022a880, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:2375 +0x1d6 +github.com/syncthing/syncthing/lib/api.getPostHandler.func1(0x4b39580, 0xc002e5f500, 0xc003ce0000) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:426 +0xe6 +net/http.HandlerFunc.ServeHTTP(0xc00030abd0, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.metricsMiddleware.func1(0x4b39580, 0xc002e5f500, 0xc003ce0000) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:518 +0x117 +net/http.HandlerFunc.ServeHTTP(0xc000010bc0, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.noCacheMiddleware.func1(0x4b39580, 0xc002e5f500, 0xc003ce0000) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:541 +0x3f4 +net/http.HandlerFunc.ServeHTTP(0xc000010be0, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.(*ServeMux).ServeHTTP(0xc00022a940, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:2375 +0x1d6 +github.com/syncthing/syncthing/lib/api.csrfMiddleware.func1(0x4b39580, 0xc002e5f500, 0xc003ce0000) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api_csrf.go:78 +0x208 +net/http.HandlerFunc.ServeHTTP(0xc0001713f0, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.withDetailsMiddleware.func1(0x4b39580, 0xc002e5f500, 0xc003ce0000) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:549 +0x2ce +net/http.HandlerFunc.ServeHTTP(0xc0000c94c0, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.basicAuthAndSessionMiddleware.func1(0x4b39580, 0xc002e5f500, 0xc003ce0000) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api_auth.go:51 +0xa64 +net/http.HandlerFunc.ServeHTTP(0xc0001e9040, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.redirectToHTTPSMiddleware.func1(0x4b39580, 0xc002e5f500, 0xc003ce0000) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:531 +0x117 +net/http.HandlerFunc.ServeHTTP(0xc0000ad700, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.corsMiddleware.func1(0x4b39580, 0xc002e5f500, 0xc003ce0000) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:510 +0x2a6 +net/http.HandlerFunc.ServeHTTP(0xc0000ad720, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.debugMiddleware.func1(0x4b39580, 0xc002e5f500, 0xc003ce0000) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:438 +0xa7 +net/http.HandlerFunc.ServeHTTP(0xc0000ad740, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.serverHandler.ServeHTTP(0xc0001e9110, 0x4b39580, 0xc002e5f500, 0xc003ce0000) + /usr/local/go/src/net/http/server.go:2774 +0xa8 +net/http.(*conn).serve(0xc00303ad20, 0x4b3b4c0, 0xc00330e880) + /usr/local/go/src/net/http/server.go:1878 +0x851 +created by net/http.(*Server).Serve + /usr/local/go/src/net/http/server.go:2884 +0x2f4 + +goroutine 84 [select]: +github.com/syncthing/syncthing/lib/fs.(*BasicFilesystem).watchLoop(0xc0000c3b90, 0x4880b35, 0x1, 0xc0000384c0, 0x14, 0xc000080600, 0xc0000d64e0, 0x4b32140, 0xc00017a120, 0x4b3b4c0, ...) + /Users/jb/dev/github.com/syncthing/syncthing/lib/fs/basicfs_watch.go:81 +0x2c8 +created by github.com/syncthing/syncthing/lib/fs.(*BasicFilesystem).Watch + /Users/jb/dev/github.com/syncthing/syncthing/lib/fs/basicfs_watch.go:59 +0x3e7 + +goroutine 85 [select]: +github.com/syncthing/syncthing/lib/watchaggregator.(*aggregator).mainLoop(0xc0000b8d00, 0xc0000d64e0, 0xc0000d6420, 0x4b4aac0, 0xc000059800) + /Users/jb/dev/github.com/syncthing/syncthing/lib/watchaggregator/aggregator.go:148 +0x38e +created by github.com/syncthing/syncthing/lib/watchaggregator.Aggregate + /Users/jb/dev/github.com/syncthing/syncthing/lib/watchaggregator/aggregator.go:132 +0xdc + +goroutine 87 [select]: +github.com/syncthing/syncthing/lib/watchaggregator.(*aggregator).mainLoop(0xc0000b8ea0, 0xc00026b140, 0xc00026af00, 0x4b4aac0, 0xc000059800) + /Users/jb/dev/github.com/syncthing/syncthing/lib/watchaggregator/aggregator.go:148 +0x38e +created by github.com/syncthing/syncthing/lib/watchaggregator.Aggregate + /Users/jb/dev/github.com/syncthing/syncthing/lib/watchaggregator/aggregator.go:132 +0xdc + +goroutine 49 [select]: +github.com/syncthing/syncthing/lib/model.(*folderSummaryService).listenForUpdates(0xc0000f2960) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/folder_summary.go:158 +0x352 +github.com/syncthing/syncthing/lib/model.serviceFunc.Serve(0xc0000347b0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/folder_summary.go:311 +0x25 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc0002691d0, 0xc000000000, 0x4b33780, 0xc0000347b0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 98 [select]: +github.com/syncthing/syncthing/lib/model.(*folderSummaryService).calculateSummaries(0xc0000f2960) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/folder_summary.go:229 +0x10c +github.com/syncthing/syncthing/lib/model.serviceFunc.Serve(0xc0000347c0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/model/folder_summary.go:311 +0x25 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc0002691d0, 0xc000000001, 0x4b33780, 0xc0000347c0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 99 [select]: +github.com/syncthing/syncthing/lib/api.(*service).Serve(0xc000118dc0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:362 +0x2424 +github.com/thejerf/suture.(*Supervisor).runService.func1(0xc000268000, 0xc000000006, 0x5741e50, 0xc000118dc0) + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:600 +0x47 +created by github.com/thejerf/suture.(*Supervisor).runService + /Users/jb/go/pkg/mod/github.com/thejerf/suture@v3.0.2+incompatible/supervisor.go:588 +0x5b + +goroutine 62 [IO wait]: +internal/poll.runtime_pollWait(0x5740a28, 0x72, 0x0) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc00014e298, 0x72, 0x0, 0x0, 0x4882e05) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).Accept(0xc00014e280, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:384 +0x1ba +net.(*netFD).accept(0xc00014e280, 0xc00007b000, 0xc000272dc8, 0x400dbf9) + /usr/local/go/src/net/fd_unix.go:238 +0x42 +net.(*TCPListener).accept(0xc0000be170, 0x8, 0x2f8, 0xc000160320) + /usr/local/go/src/net/tcpsock_posix.go:139 +0x32 +net.(*TCPListener).Accept(0xc0000be170, 0x203000, 0x0, 0x405dea2, 0x404d39c) + /usr/local/go/src/net/tcpsock.go:260 +0x48 +github.com/syncthing/syncthing/lib/tlsutil.(*DowngradingListener).AcceptNoWrapTLS(0xc000010b20, 0x100000001, 0xc000272e48, 0x404f208, 0x460f5132d1e8, 0xc03447be48) + /Users/jb/dev/github.com/syncthing/syncthing/lib/tlsutil/tlsutil.go:189 +0x37 +github.com/syncthing/syncthing/lib/tlsutil.(*DowngradingListener).Accept(0xc000010b20, 0xc000272ec0, 0x18, 0xc0002c9500, 0x4325f54) + /Users/jb/dev/github.com/syncthing/syncthing/lib/tlsutil/tlsutil.go:170 +0x2f +net/http.(*Server).Serve(0xc0001e9110, 0x4b38dc0, 0xc000010b20, 0x0, 0x0) + /usr/local/go/src/net/http/server.go:2859 +0x22d +github.com/syncthing/syncthing/lib/api.(*service).Serve.func1(0xc000080ae0, 0xc0001e9110, 0x4b38dc0, 0xc000010b20) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:357 +0x3f +created by github.com/syncthing/syncthing/lib/api.(*service).Serve + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:356 +0x2363 + +goroutine 64 [select]: +net/http.(*persistConn).writeLoop(0xc0000d0b40) + /usr/local/go/src/net/http/transport.go:1958 +0x113 +created by net/http.(*Transport).dialConn + /usr/local/go/src/net/http/transport.go:1358 +0xb0d + +goroutine 156 [IO wait]: +internal/poll.runtime_pollWait(0x5740068, 0x72, 0xffffffffffffffff) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc001002298, 0x72, 0x600, 0x62b, 0xffffffffffffffff) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).Read(0xc001002280, 0xc000c12000, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:169 +0x1f2 +net.(*netFD).Read(0xc001002280, 0xc000c12000, 0x62b, 0x62b, 0xc0002f58c0, 0x8, 0xc000f71c80) + /usr/local/go/src/net/fd_unix.go:202 +0x4f +net.(*conn).Read(0xc003046190, 0xc000c12000, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/net/net.go:177 +0x69 +github.com/syncthing/syncthing/lib/tlsutil.(*UnionedConnection).Read(0xc003482ea0, 0xc000c12000, 0x62b, 0x62b, 0xc0002f5900, 0xc0002f59a8, 0x10) + /Users/jb/dev/github.com/syncthing/syncthing/lib/tlsutil/tlsutil.go:223 +0xc1 +crypto/tls.(*atLeastReader).Read(0xc0002392c0, 0xc000c12000, 0x62b, 0x62b, 0xc00409a5a5, 0xc001002298, 0xc0002f59d8) + /usr/local/go/src/crypto/tls/conn.go:761 +0x60 +bytes.(*Buffer).ReadFrom(0xc0000b1e58, 0x4b2a4a0, 0xc0002392c0, 0x400bc55, 0x47b4f40, 0x4812c80) + /usr/local/go/src/bytes/buffer.go:207 +0xbd +crypto/tls.(*Conn).readFromUntil(0xc0000b1c00, 0x572adf0, 0xc003482ea0, 0x5, 0xc003482ea0, 0x1e0) + /usr/local/go/src/crypto/tls/conn.go:783 +0xf8 +crypto/tls.(*Conn).readRecordOrCCS(0xc0000b1c00, 0x4a46f00, 0xc0000b1d38, 0x431b6ba) + /usr/local/go/src/crypto/tls/conn.go:590 +0x125 +crypto/tls.(*Conn).readRecord(...) + /usr/local/go/src/crypto/tls/conn.go:558 +crypto/tls.(*Conn).Read(0xc0000b1c00, 0xc002e1c000, 0x1000, 0x1000, 0x0, 0x0, 0x0) + /usr/local/go/src/crypto/tls/conn.go:1236 +0x137 +net/http.(*connReader).Read(0xc000a76510, 0xc002e1c000, 0x1000, 0x1000, 0x425ea21, 0xc003482ea0, 0xbf2f613ef999e150) + /usr/local/go/src/net/http/server.go:787 +0x107 +bufio.(*Reader).fill(0xc003716e40) + /usr/local/go/src/bufio/bufio.go:100 +0x10f +bufio.(*Reader).Peek(0xc003716e40, 0x4, 0x435f745b6, 0x50bfa40, 0x0, 0x0, 0x50bfa40) + /usr/local/go/src/bufio/bufio.go:138 +0x4f +net/http.(*conn).serve(0xc000160320, 0x4b3b4c0, 0xc00317a000) + /usr/local/go/src/net/http/server.go:1903 +0x9bf +created by net/http.(*Server).Serve + /usr/local/go/src/net/http/server.go:2884 +0x2f4 + +goroutine 93 [runnable]: +io.(*LimitedReader).Read(0xc003a0e840, 0xc003fca000, 0x8000, 0x8000, 0x8000, 0x0, 0x0) + /usr/local/go/src/io/io.go:441 +0xc9 +io.copyBuffer(0x5741150, 0xc000a35030, 0x4b2aee0, 0xc003a0e840, 0xc003fca000, 0x8000, 0x8000, 0x20000, 0x0, 0x0) + /usr/local/go/src/io/io.go:402 +0x122 +io.CopyBuffer(...) + /usr/local/go/src/io/io.go:375 +github.com/syncthing/syncthing/lib/scanner.Blocks(0x4b3b500, 0xc0000c4030, 0x4b2a360, 0xc000c47ec0, 0x20000, 0x200000, 0x4b2a940, 0x50e2748, 0x4059500, 0xc003384300, ...) + /Users/jb/dev/github.com/syncthing/syncthing/lib/scanner/blocks.go:69 +0x330 +github.com/syncthing/syncthing/lib/ur.cpuBenchOnce(0x7735940, 0xc0014d2000, 0xc0014d2000, 0x200000, 0x200000, 0x4051e3d70a3d70a4) + /Users/jb/dev/github.com/syncthing/syncthing/lib/ur/usage_report.go:468 +0x153 +github.com/syncthing/syncthing/lib/ur.CpuBench(0x5, 0x7735940, 0x488a100, 0xe) + /Users/jb/dev/github.com/syncthing/syncthing/lib/ur/usage_report.go:453 +0xd4 +github.com/syncthing/syncthing/lib/ur.(*Service).reportData(0xc0002461c0, 0x3, 0x1, 0x4b2b580) + /Users/jb/dev/github.com/syncthing/syncthing/lib/ur/usage_report.go:111 +0x8ad +github.com/syncthing/syncthing/lib/ur.(*Service).ReportDataPreview(...) + /Users/jb/dev/github.com/syncthing/syncthing/lib/ur/usage_report.go:75 +github.com/syncthing/syncthing/lib/api.(*service).getReport(0xc000118dc0, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:1102 +0x7f +net/http.HandlerFunc.ServeHTTP(0xc002ef2190, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.(*ServeMux).ServeHTTP(0xc00022a880, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:2375 +0x1d6 +github.com/syncthing/syncthing/lib/api.getPostHandler.func1(0x4b39580, 0xc0011160e0, 0xc003ce0900) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:426 +0xe6 +net/http.HandlerFunc.ServeHTTP(0xc00030abd0, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.metricsMiddleware.func1(0x4b39580, 0xc0011160e0, 0xc003ce0900) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:518 +0x117 +net/http.HandlerFunc.ServeHTTP(0xc000010bc0, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.noCacheMiddleware.func1(0x4b39580, 0xc0011160e0, 0xc003ce0900) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:541 +0x3f4 +net/http.HandlerFunc.ServeHTTP(0xc000010be0, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.(*ServeMux).ServeHTTP(0xc00022a940, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:2375 +0x1d6 +github.com/syncthing/syncthing/lib/api.csrfMiddleware.func1(0x4b39580, 0xc0011160e0, 0xc003ce0900) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api_csrf.go:78 +0x208 +net/http.HandlerFunc.ServeHTTP(0xc0001713f0, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.withDetailsMiddleware.func1(0x4b39580, 0xc0011160e0, 0xc003ce0900) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:549 +0x2ce +net/http.HandlerFunc.ServeHTTP(0xc0000c94c0, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.basicAuthAndSessionMiddleware.func1(0x4b39580, 0xc0011160e0, 0xc003ce0900) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api_auth.go:51 +0xa64 +net/http.HandlerFunc.ServeHTTP(0xc0001e9040, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.redirectToHTTPSMiddleware.func1(0x4b39580, 0xc0011160e0, 0xc003ce0900) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:531 +0x117 +net/http.HandlerFunc.ServeHTTP(0xc0000ad700, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.corsMiddleware.func1(0x4b39580, 0xc0011160e0, 0xc003ce0900) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:510 +0x2a6 +net/http.HandlerFunc.ServeHTTP(0xc0000ad720, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:1995 +0x44 +github.com/syncthing/syncthing/lib/api.debugMiddleware.func1(0x4b39580, 0xc0011160e0, 0xc003ce0900) + /Users/jb/dev/github.com/syncthing/syncthing/lib/api/api.go:438 +0xa7 +net/http.HandlerFunc.ServeHTTP(0xc0000ad740, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:1995 +0x44 +net/http.serverHandler.ServeHTTP(0xc0001e9110, 0x4b39580, 0xc0011160e0, 0xc003ce0900) + /usr/local/go/src/net/http/server.go:2774 +0xa8 +net/http.(*conn).serve(0xc00303bc20, 0x4b3b4c0, 0xc00133d380) + /usr/local/go/src/net/http/server.go:1878 +0x851 +created by net/http.(*Server).Serve + /usr/local/go/src/net/http/server.go:2884 +0x2f4 + +goroutine 121 [IO wait]: +internal/poll.runtime_pollWait(0x57403a8, 0x72, 0xffffffffffffffff) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc001729d98, 0x72, 0x600, 0x62b, 0xffffffffffffffff) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).Read(0xc001729d80, 0xc0034c2300, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:169 +0x1f2 +net.(*netFD).Read(0xc001729d80, 0xc0034c2300, 0x62b, 0x62b, 0xc003f3f8c0, 0x8, 0xc000357200) + /usr/local/go/src/net/fd_unix.go:202 +0x4f +net.(*conn).Read(0xc0011999f0, 0xc0034c2300, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/net/net.go:177 +0x69 +github.com/syncthing/syncthing/lib/tlsutil.(*UnionedConnection).Read(0xc00368a0e0, 0xc0034c2300, 0x62b, 0x62b, 0xc003f3f900, 0xc003f3f9a8, 0x10) + /Users/jb/dev/github.com/syncthing/syncthing/lib/tlsutil/tlsutil.go:223 +0xc1 +crypto/tls.(*atLeastReader).Read(0xc000239240, 0xc0034c2300, 0x62b, 0x62b, 0xc00337e005, 0xc001729d98, 0xc003f3f9d8) + /usr/local/go/src/crypto/tls/conn.go:761 +0x60 +bytes.(*Buffer).ReadFrom(0xc0000b1058, 0x4b2a4a0, 0xc000239240, 0x400bc55, 0x47b4f40, 0x4812c80) + /usr/local/go/src/bytes/buffer.go:207 +0xbd +crypto/tls.(*Conn).readFromUntil(0xc0000b0e00, 0x572adf0, 0xc00368a0e0, 0x5, 0xc00368a0e0, 0x1e0) + /usr/local/go/src/crypto/tls/conn.go:783 +0xf8 +crypto/tls.(*Conn).readRecordOrCCS(0xc0000b0e00, 0x4a46f00, 0xc0000b0f38, 0x431b6ba) + /usr/local/go/src/crypto/tls/conn.go:590 +0x125 +crypto/tls.(*Conn).readRecord(...) + /usr/local/go/src/crypto/tls/conn.go:558 +crypto/tls.(*Conn).Read(0xc0000b0e00, 0xc003882000, 0x1000, 0x1000, 0x0, 0x0, 0x0) + /usr/local/go/src/crypto/tls/conn.go:1236 +0x137 +net/http.(*connReader).Read(0xc0036d64e0, 0xc003882000, 0x1000, 0x1000, 0x425ea21, 0xc00368a0e0, 0xbf2f613ef96cb2e8) + /usr/local/go/src/net/http/server.go:787 +0x107 +bufio.(*Reader).fill(0xc0034beae0) + /usr/local/go/src/bufio/bufio.go:100 +0x10f +bufio.(*Reader).Peek(0xc0034beae0, 0x4, 0x435ca1921, 0x50bfa40, 0x0, 0x0, 0x50bfa40) + /usr/local/go/src/bufio/bufio.go:138 +0x4f +net/http.(*conn).serve(0xc00303b540, 0x4b3b4c0, 0xc00330e600) + /usr/local/go/src/net/http/server.go:1903 +0x9bf +created by net/http.(*Server).Serve + /usr/local/go/src/net/http/server.go:2884 +0x2f4 + +goroutine 119 [IO wait]: +internal/poll.runtime_pollWait(0x57406e8, 0x72, 0xffffffffffffffff) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc00014d518, 0x72, 0x600, 0x62b, 0xffffffffffffffff) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).Read(0xc00014d500, 0xc00382ce00, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:169 +0x1f2 +net.(*netFD).Read(0xc00014d500, 0xc00382ce00, 0x62b, 0x62b, 0xc0002f98c0, 0x8, 0xc0002c9380) + /usr/local/go/src/net/fd_unix.go:202 +0x4f +net.(*conn).Read(0xc0030465e0, 0xc00382ce00, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/net/net.go:177 +0x69 +github.com/syncthing/syncthing/lib/tlsutil.(*UnionedConnection).Read(0xc002d80ae0, 0xc00382ce00, 0x62b, 0x62b, 0xc0002f9900, 0xc0002f99a8, 0x10) + /Users/jb/dev/github.com/syncthing/syncthing/lib/tlsutil/tlsutil.go:223 +0xc1 +crypto/tls.(*atLeastReader).Read(0xc003d98a40, 0xc00382ce00, 0x62b, 0x62b, 0xc0000f0a05, 0xc00014d518, 0xc0002f99d8) + /usr/local/go/src/crypto/tls/conn.go:761 +0x60 +bytes.(*Buffer).ReadFrom(0xc0000b0cd8, 0x4b2a4a0, 0xc003d98a40, 0x400bc55, 0x47b4f40, 0x4812c80) + /usr/local/go/src/bytes/buffer.go:207 +0xbd +crypto/tls.(*Conn).readFromUntil(0xc0000b0a80, 0x572adf0, 0xc002d80ae0, 0x5, 0xc002d80ae0, 0x1500) + /usr/local/go/src/crypto/tls/conn.go:783 +0xf8 +crypto/tls.(*Conn).readRecordOrCCS(0xc0000b0a80, 0x4a46f00, 0xc0000b0bb8, 0x431b6ba) + /usr/local/go/src/crypto/tls/conn.go:590 +0x125 +crypto/tls.(*Conn).readRecord(...) + /usr/local/go/src/crypto/tls/conn.go:558 +crypto/tls.(*Conn).Read(0xc0000b0a80, 0xc00129a000, 0x1000, 0x1000, 0x0, 0x0, 0x0) + /usr/local/go/src/crypto/tls/conn.go:1236 +0x137 +net/http.(*connReader).Read(0xc000e40d20, 0xc00129a000, 0x1000, 0x1000, 0x425ea21, 0xc002d80ae0, 0xbf2f613ef998b488) + /usr/local/go/src/net/http/server.go:787 +0x107 +bufio.(*Reader).fill(0xc000fcc240) + /usr/local/go/src/bufio/bufio.go:100 +0x10f +bufio.(*Reader).Peek(0xc000fcc240, 0x4, 0x435f619b6, 0x50bfa40, 0x0, 0x0, 0x50bfa40) + /usr/local/go/src/bufio/bufio.go:138 +0x4f +net/http.(*conn).serve(0xc0000f34a0, 0x4b3b4c0, 0xc00389d680) + /usr/local/go/src/net/http/server.go:1903 +0x9bf +created by net/http.(*Server).Serve + /usr/local/go/src/net/http/server.go:2884 +0x2f4 + +goroutine 184 [IO wait]: +internal/poll.runtime_pollWait(0x5740478, 0x72, 0xffffffffffffffff) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc0005e5b98, 0x72, 0x600, 0x611, 0xffffffffffffffff) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).Read(0xc0005e5b80, 0xc002e3c000, 0x611, 0x611, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:169 +0x1f2 +net.(*netFD).Read(0xc0005e5b80, 0xc002e3c000, 0x611, 0x611, 0x203000, 0x0, 0xc000000034) + /usr/local/go/src/net/fd_unix.go:202 +0x4f +net.(*conn).Read(0xc003046048, 0xc002e3c000, 0x611, 0x611, 0x0, 0x0, 0x0) + /usr/local/go/src/net/net.go:177 +0x69 +crypto/tls.(*atLeastReader).Read(0xc003d98b40, 0xc002e3c000, 0x611, 0x611, 0x2, 0xa, 0xc0013c8938) + /usr/local/go/src/crypto/tls/conn.go:761 +0x60 +bytes.(*Buffer).ReadFrom(0xc0000b13d8, 0x4b2a4a0, 0xc003d98b40, 0x400bc55, 0x47b4f40, 0x4852500) + /usr/local/go/src/bytes/buffer.go:207 +0xbd +crypto/tls.(*Conn).readFromUntil(0xc0000b1180, 0x5712c90, 0xc003046048, 0x5, 0xc003046048, 0x203000) + /usr/local/go/src/crypto/tls/conn.go:783 +0xf8 +crypto/tls.(*Conn).readRecordOrCCS(0xc0000b1180, 0x4a46f00, 0xc0000b12b8, 0xc0013c8b88) + /usr/local/go/src/crypto/tls/conn.go:590 +0x125 +crypto/tls.(*Conn).readRecord(...) + /usr/local/go/src/crypto/tls/conn.go:558 +crypto/tls.(*Conn).Read(0xc0000b1180, 0xc001ab5000, 0x1000, 0x1000, 0x0, 0x0, 0x0) + /usr/local/go/src/crypto/tls/conn.go:1236 +0x137 +net/http.(*persistConn).Read(0xc00019cd80, 0xc001ab5000, 0x1000, 0x1000, 0xc0013c8c88, 0x4006d35, 0xc000baa960) + /usr/local/go/src/net/http/transport.go:1524 +0x7b +bufio.(*Reader).fill(0xc000fccf60) + /usr/local/go/src/bufio/bufio.go:100 +0x10f +bufio.(*Reader).Peek(0xc000fccf60, 0x1, 0x0, 0x0, 0x1, 0xc000baa800, 0x0) + /usr/local/go/src/bufio/bufio.go:138 +0x4f +net/http.(*persistConn).readLoop(0xc00019cd80) + /usr/local/go/src/net/http/transport.go:1677 +0x1a3 +created by net/http.(*Transport).dialConn + /usr/local/go/src/net/http/transport.go:1357 +0xae8 + +goroutine 154 [IO wait]: +internal/poll.runtime_pollWait(0x5740138, 0x72, 0xffffffffffffffff) + /usr/local/go/src/runtime/netpoll.go:182 +0x56 +internal/poll.(*pollDesc).wait(0xc0000cd698, 0x72, 0x600, 0x62b, 0xffffffffffffffff) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x9b +internal/poll.(*pollDesc).waitRead(...) + /usr/local/go/src/internal/poll/fd_poll_runtime.go:92 +internal/poll.(*FD).Read(0xc0000cd680, 0xc0034c0000, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/internal/poll/fd_unix.go:169 +0x1f2 +net.(*netFD).Read(0xc0000cd680, 0xc0034c0000, 0x62b, 0x62b, 0xc0037a98c0, 0x8, 0x4a46af0) + /usr/local/go/src/net/fd_unix.go:202 +0x4f +net.(*conn).Read(0xc000b1f630, 0xc0034c0000, 0x62b, 0x62b, 0x0, 0x0, 0x0) + /usr/local/go/src/net/net.go:177 +0x69 +github.com/syncthing/syncthing/lib/tlsutil.(*UnionedConnection).Read(0xc003482b40, 0xc0034c0000, 0x62b, 0x62b, 0xc0037a9900, 0xc0037a99a8, 0x10) + /Users/jb/dev/github.com/syncthing/syncthing/lib/tlsutil/tlsutil.go:223 +0xc1 +crypto/tls.(*atLeastReader).Read(0xc003d98a20, 0xc0034c0000, 0x62b, 0x62b, 0xc00409a3c5, 0xc0000cd698, 0xc0037a99d8) + /usr/local/go/src/crypto/tls/conn.go:761 +0x60 +bytes.(*Buffer).ReadFrom(0xc0000b1ad8, 0x4b2a4a0, 0xc003d98a20, 0x400bc55, 0x47b4f40, 0x4812c80) + /usr/local/go/src/bytes/buffer.go:207 +0xbd +crypto/tls.(*Conn).readFromUntil(0xc0000b1880, 0x572adf0, 0xc003482b40, 0x5, 0xc003482b40, 0x1e0) + /usr/local/go/src/crypto/tls/conn.go:783 +0xf8 +crypto/tls.(*Conn).readRecordOrCCS(0xc0000b1880, 0x4a46f00, 0xc0000b19b8, 0x431b6ba) + /usr/local/go/src/crypto/tls/conn.go:590 +0x125 +crypto/tls.(*Conn).readRecord(...) + /usr/local/go/src/crypto/tls/conn.go:558 +crypto/tls.(*Conn).Read(0xc0000b1880, 0xc0017cf000, 0x1000, 0x1000, 0x0, 0x0, 0x0) + /usr/local/go/src/crypto/tls/conn.go:1236 +0x137 +net/http.(*connReader).Read(0xc000a774d0, 0xc0017cf000, 0x1000, 0x1000, 0x425ea21, 0xc003482b40, 0xbf2f613ef9985ab0) + /usr/local/go/src/net/http/server.go:787 +0x107 +bufio.(*Reader).fill(0xc0037171a0) + /usr/local/go/src/bufio/bufio.go:100 +0x10f +bufio.(*Reader).Peek(0xc0037171a0, 0x4, 0x435f5c239, 0x50bfa40, 0x0, 0x0, 0x50bfa40) + /usr/local/go/src/bufio/bufio.go:138 +0x4f +net/http.(*conn).serve(0xc000160000, 0x4b3b4c0, 0xc00317a100) + /usr/local/go/src/net/http/server.go:1903 +0x9bf +created by net/http.(*Server).Serve + /usr/local/go/src/net/http/server.go:2884 +0x2f4 + +goroutine 185 [select]: +net/http.(*persistConn).writeLoop(0xc00019cd80) + /usr/local/go/src/net/http/transport.go:1958 +0x113 +created by net/http.(*Transport).dialConn + /usr/local/go/src/net/http/transport.go:1358 +0xb0d + +goroutine 172 [semacquire]: +sync.runtime_Semacquire(0xc003d18518) + /usr/local/go/src/runtime/sema.go:56 +0x39 +sync.(*WaitGroup).Wait(0xc003d18510) + /usr/local/go/src/sync/waitgroup.go:130 +0x65 +github.com/syncthing/syncthing/lib/connections.(*service).dialParallel.func2(0xc003d18510, 0xc0034bf3e0) + /Users/jb/dev/github.com/syncthing/syncthing/lib/connections/service.go:849 +0x2b +created by github.com/syncthing/syncthing/lib/connections.(*service).dialParallel + /Users/jb/dev/github.com/syncthing/syncthing/lib/connections/service.go:848 +0x494 diff --git a/cmd/stcrashreceiver/sentry.go b/cmd/stcrashreceiver/sentry.go new file mode 100644 index 000000000..fd679a14e --- /dev/null +++ b/cmd/stcrashreceiver/sentry.go @@ -0,0 +1,160 @@ +// Copyright (C) 2019 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +package main + +import ( + "bytes" + "errors" + "io/ioutil" + "regexp" + "strings" + + raven "github.com/getsentry/raven-go" + "github.com/maruel/panicparse/stack" +) + +const reportServer = "https://crash.syncthing.net/report/" + +func sendReport(dsn, path string, report []byte) error { + pkt, err := parseReport(path, report) + if err != nil { + return err + } + + cli, err := raven.New(dsn) + if err != nil { + return err + } + + // The client sets release and such on the packet before sending, in the + // misguided idea that it knows this better than than the packet we give + // it. So we copy the values from the packet to the client first... + cli.SetRelease(pkt.Release) + cli.SetEnvironment(pkt.Environment) + + _, errC := cli.Capture(pkt, nil) + return <-errC +} + +func parseReport(path string, report []byte) (*raven.Packet, error) { + parts := bytes.SplitN(report, []byte("\n"), 2) + if len(parts) != 2 { + return nil, errors.New("no first line") + } + + version, err := parseVersion(string(parts[0])) + if err != nil { + return nil, err + } + report = parts[1] + + foundPanic := false + var subjectLine []byte + for { + parts = bytes.SplitN(report, []byte("\n"), 2) + if len(parts) != 2 { + return nil, errors.New("no panic line found") + } + + line := parts[0] + report = parts[1] + + if foundPanic { + // The previous line was our "Panic at ..." header. We are now + // at the beginning of the real panic trace and this is our + // subject line. + subjectLine = line + break + } else if bytes.HasPrefix(line, []byte("Panic at")) { + foundPanic = true + } + } + + r := bytes.NewReader(report) + ctx, err := stack.ParseDump(r, ioutil.Discard, false) + if err != nil { + return nil, err + } + + var trace raven.Stacktrace + for _, gr := range ctx.Goroutines { + if gr.First { + trace.Frames = make([]*raven.StacktraceFrame, len(gr.Stack.Calls)) + for i, sc := range gr.Stack.Calls { + trace.Frames[len(trace.Frames)-1-i] = &raven.StacktraceFrame{ + Function: sc.Func.Name(), + Module: sc.Func.PkgName(), + Filename: sc.SrcPath, + Lineno: sc.Line, + } + } + break + } + } + + pkt := &raven.Packet{ + Message: string(subjectLine), + Platform: "go", + Release: version.tag, + Tags: raven.Tags{ + raven.Tag{Key: "version", Value: version.version}, + raven.Tag{Key: "tag", Value: version.tag}, + raven.Tag{Key: "commit", Value: version.commit}, + raven.Tag{Key: "codename", Value: version.codename}, + raven.Tag{Key: "runtime", Value: version.runtime}, + raven.Tag{Key: "goos", Value: version.goos}, + raven.Tag{Key: "goarch", Value: version.goarch}, + raven.Tag{Key: "builder", Value: version.builder}, + }, + Extra: raven.Extra{ + "url": reportServer + path, + }, + Interfaces: []raven.Interface{&trace}, + } + + return pkt, nil +} + +// syncthing v1.1.4-rc.1+30-g6aaae618-dirty-crashrep "Erbium Earthworm" (go1.12.5 darwin-amd64) jb@kvin.kastelo.net 2019-05-23 16:08:14 UTC +var longVersionRE = regexp.MustCompile(`syncthing\s+(v[^\s]+)\s+"([^"]+)"\s\(([^\s]+)\s+([^-]+)-([^)]+)\)\s+([^\s]+)`) + +type version struct { + version string // "v1.1.4-rc.1+30-g6aaae618-dirty-crashrep" + tag string // "v1.1.4-rc.1" + commit string // "6aaae618", blank when absent + codename string // "Erbium Earthworm" + runtime string // "go1.12.5" + goos string // "darwin" + goarch string // "amd64" + builder string // "jb@kvin.kastelo.net" +} + +func parseVersion(line string) (version, error) { + m := longVersionRE.FindStringSubmatch(line) + if len(m) == 0 { + return version{}, errors.New("unintelligeble version string") + } + + v := version{ + version: m[1], + codename: m[2], + runtime: m[3], + goos: m[4], + goarch: m[5], + builder: m[6], + } + parts := strings.Split(v.version, "+") + v.tag = parts[0] + if len(parts) > 1 { + fields := strings.Split(parts[1], "-") + if len(fields) >= 2 && strings.HasPrefix(fields[1], "g") { + v.commit = fields[1][1:] + } + } + + return v, nil +} diff --git a/cmd/stcrashreceiver/sentry_test.go b/cmd/stcrashreceiver/sentry_test.go new file mode 100644 index 000000000..cd5137bf1 --- /dev/null +++ b/cmd/stcrashreceiver/sentry_test.go @@ -0,0 +1,64 @@ +// Copyright (C) 2019 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +package main + +import ( + "fmt" + "io/ioutil" + "testing" +) + +func TestParseVersion(t *testing.T) { + cases := []struct { + longVersion string + parsed version + }{ + { + longVersion: `syncthing v1.1.4-rc.1+30-g6aaae618-dirty-crashrep "Erbium Earthworm" (go1.12.5 darwin-amd64) jb@kvin.kastelo.net 2019-05-23 16:08:14 UTC`, + parsed: version{ + version: "v1.1.4-rc.1+30-g6aaae618-dirty-crashrep", + tag: "v1.1.4-rc.1", + commit: "6aaae618", + codename: "Erbium Earthworm", + runtime: "go1.12.5", + goos: "darwin", + goarch: "amd64", + builder: "jb@kvin.kastelo.net", + }, + }, + } + + for _, tc := range cases { + v, err := parseVersion(tc.longVersion) + if err != nil { + t.Error(err) + continue + } + if v != tc.parsed { + t.Error(v) + } + } +} + +func TestParseReport(t *testing.T) { + bs, err := ioutil.ReadFile("_testdata/panic.log") + if err != nil { + t.Fatal(err) + } + + pkt, err := parseReport("1/2/345", bs) + if err != nil { + t.Fatal(err) + } + + bs, err = pkt.JSON() + if err != nil { + t.Fatal(err) + } + + fmt.Printf("%s\n", bs) +} diff --git a/cmd/stcrashreceiver/stcrashreceiver.go b/cmd/stcrashreceiver/stcrashreceiver.go new file mode 100644 index 000000000..534a7e0f7 --- /dev/null +++ b/cmd/stcrashreceiver/stcrashreceiver.go @@ -0,0 +1,135 @@ +// Copyright (C) 2019 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +// Command stcrashreceiver is a trivial HTTP server that allows two things: +// +// - uploading files (crash reports) named like a SHA256 hash using a PUT request +// - checking whether such file exists using a HEAD request +// +// Typically this should be deployed behind something that manages HTTPS. +package main + +import ( + "flag" + "io" + "io/ioutil" + "log" + "net/http" + "os" + "path" + "path/filepath" + "strings" +) + +const maxRequestSize = 1 << 20 // 1 MiB + +func main() { + dir := flag.String("dir", ".", "Directory to store reports in") + dsn := flag.String("dsn", "", "Sentry DSN") + listen := flag.String("listen", ":22039", "HTTP listen address") + flag.Parse() + + cr := &crashReceiver{ + dir: *dir, + dsn: *dsn, + } + + log.SetOutput(os.Stdout) + if err := http.ListenAndServe(*listen, cr); err != nil { + log.Fatalln("HTTP serve:", err) + } +} + +type crashReceiver struct { + dir string + dsn string +} + +func (r *crashReceiver) ServeHTTP(w http.ResponseWriter, req *http.Request) { + // The final path component should be a SHA256 hash in hex, so 64 hex + // characters. We don't care about case on the request but use lower + // case internally. + base := strings.ToLower(path.Base(req.URL.Path)) + if len(base) != 64 { + http.Error(w, "Bad request", http.StatusBadRequest) + return + } + for _, c := range base { + if c >= 'a' && c <= 'f' { + continue + } + if c >= '0' && c <= '9' { + continue + } + http.Error(w, "Bad request", http.StatusBadRequest) + return + } + + switch req.Method { + case http.MethodHead: + r.serveHead(base, w, req) + case http.MethodPut: + r.servePut(base, w, req) + default: + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + } +} + +// serveHead responds to HEAD requests by checking if the named report +// already exists in the system. +func (r *crashReceiver) serveHead(base string, w http.ResponseWriter, _ *http.Request) { + path := filepath.Join(r.dirFor(base), base) + if _, err := os.Lstat(path); err != nil { + http.Error(w, "Not found", http.StatusNotFound) + } + // 200 OK +} + +// servePut accepts and stores the given report. +func (r *crashReceiver) servePut(base string, w http.ResponseWriter, req *http.Request) { + path := filepath.Join(r.dirFor(base), base) + fullPath := filepath.Join(r.dir, path) + + // Ensure the destination directory exists + if err := os.MkdirAll(filepath.Dir(fullPath), 0755); err != nil { + log.Printf("Creating directory for report %s: %v", base, err) + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + + // Read at most maxRequestSize of report data. + log.Println("Receiving report", base) + lr := io.LimitReader(req.Body, maxRequestSize) + bs, err := ioutil.ReadAll(lr) + if err != nil { + log.Println("Reading report:", err) + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + + // Create an output file + err = ioutil.WriteFile(fullPath, bs, 0644) + if err != nil { + log.Printf("Creating file for report %s: %v", base, err) + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + + // Send the report to Sentry + if r.dsn != "" { + go func() { + // There's no need for the client to have to wait for this part. + if err := sendReport(r.dsn, path, bs); err != nil { + log.Println("Failed to send report:", err) + } + }() + } +} + +// 01234567890abcdef... => 01/23 +func (r *crashReceiver) dirFor(base string) string { + return filepath.Join(base[0:2], base[2:4]) +} diff --git a/cmd/syncthing/crash_reporting.go b/cmd/syncthing/crash_reporting.go new file mode 100644 index 000000000..828695f1a --- /dev/null +++ b/cmd/syncthing/crash_reporting.go @@ -0,0 +1,152 @@ +// Copyright (C) 2019 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +package main + +import ( + "bytes" + "context" + "fmt" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "sort" + "strings" + "time" + + "github.com/syncthing/syncthing/lib/sha256" +) + +const ( + headRequestTimeout = 10 * time.Second + putRequestTimeout = time.Minute +) + +// uploadPanicLogs attempts to upload all the panic logs in the named +// directory to the crash reporting server as urlBase. Uploads are attempted +// with the newest log first. +// +// This can can block for a long time. The context can set a final deadline +// for this. +func uploadPanicLogs(ctx context.Context, urlBase, dir string) { + files, err := filepath.Glob(filepath.Join(dir, "panic-*.log")) + if err != nil { + l.Warnln("Failed to list panic logs:", err) + return + } + + sort.Sort(sort.Reverse(sort.StringSlice(files))) + for _, file := range files { + if strings.Contains(file, ".reported.") { + // We've already sent this file. It'll be cleaned out at some + // point. + continue + } + + if err := uploadPanicLog(ctx, urlBase, file); err != nil { + l.Warnln("Reporting crash:", err) + } else { + // Rename the log so we don't have to try to report it again. This + // succeeds, or it does not. There is no point complaining about it. + _ = os.Rename(file, strings.Replace(file, ".log", ".reported.log", 1)) + } + } +} + +// uploadPanicLog attempts to upload the named panic log to the crash +// reporting server at urlBase. The panic ID is constructed as the sha256 of +// the log contents. A HEAD request is made to see if the log has already +// been reported. If not, a PUT is made with the log contents. +func uploadPanicLog(ctx context.Context, urlBase, file string) error { + data, err := ioutil.ReadFile(file) + if err != nil { + return err + } + + // Remove log lines, for privacy. + data = filterLogLines(data) + + hash := fmt.Sprintf("%x", sha256.Sum256(data)) + l.Infof("Reporting crash found in %s (report ID %s) ...\n", filepath.Base(file), hash[:8]) + + url := fmt.Sprintf("%s/%s", urlBase, hash) + headReq, err := http.NewRequest(http.MethodHead, url, nil) + if err != nil { + return err + } + + // Set a reasonable timeout on the HEAD request + headCtx, headCancel := context.WithTimeout(ctx, headRequestTimeout) + defer headCancel() + headReq = headReq.WithContext(headCtx) + + resp, err := http.DefaultClient.Do(headReq) + if err != nil { + return err + } + resp.Body.Close() + if resp.StatusCode == http.StatusOK { + // It's known, we're done + return nil + } + + putReq, err := http.NewRequest(http.MethodPut, url, bytes.NewReader(data)) + if err != nil { + return err + } + + // Set a reasonable timeout on the PUT request + putCtx, putCancel := context.WithTimeout(ctx, putRequestTimeout) + defer putCancel() + putReq = putReq.WithContext(putCtx) + + resp, err = http.DefaultClient.Do(putReq) + if err != nil { + return err + } + resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("upload: %s", resp.Status) + } + + return nil +} + +// filterLogLines returns the data without any log lines between the first +// line and the panic trace. This is done in-place: the original data slice +// is destroyed. +func filterLogLines(data []byte) []byte { + filtered := data[:0] + matched := false + for _, line := range bytes.Split(data, []byte("\n")) { + switch { + case !matched && bytes.HasPrefix(line, []byte("Panic ")): + // This begins the panic trace, set the matched flag and append. + matched = true + fallthrough + case len(filtered) == 0 || matched: + // This is the first line or inside the panic trace. + if len(filtered) > 0 { + // We add the newline before rather than after because + // bytes.Split sees the \n as *separator* and not line + // ender, so ir will generate a last empty line that we + // don't really want. (We want to keep blank lines in the + // middle of the trace though.) + filtered = append(filtered, '\n') + } + // Remove the device ID prefix. The "plus two" stuff is because + // the line will look like "[foo] whatever" and the end variable + // will end up pointing at the ] and we want to step over that + // and the following space. + if end := bytes.Index(line, []byte("]")); end > 1 && end < len(line)-2 && bytes.HasPrefix(line, []byte("[")) { + line = line[end+2:] + } + filtered = append(filtered, line...) + } + } + return filtered +} diff --git a/cmd/syncthing/crash_reporting_test.go b/cmd/syncthing/crash_reporting_test.go new file mode 100644 index 000000000..045a10187 --- /dev/null +++ b/cmd/syncthing/crash_reporting_test.go @@ -0,0 +1,37 @@ +// Copyright (C) 2019 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +package main + +import ( + "bytes" + "testing" +) + +func TestFilterLogLines(t *testing.T) { + in := []byte(`[ABCD123] syncthing version whatever +here is more log data +and more +... +and some more +yet more +Panic detected at like right now +here is panic data +and yet more panic stuff +`) + + filtered := []byte(`syncthing version whatever +Panic detected at like right now +here is panic data +and yet more panic stuff +`) + + result := filterLogLines(in) + if !bytes.Equal(result, filtered) { + t.Logf("%q\n", result) + t.Error("it should have been filtered") + } +} diff --git a/cmd/syncthing/monitor.go b/cmd/syncthing/monitor.go index 20b26c21d..8668abdd7 100644 --- a/cmd/syncthing/monitor.go +++ b/cmd/syncthing/monitor.go @@ -8,6 +8,7 @@ package main import ( "bufio" + "context" "io" "os" "os/exec" @@ -33,6 +34,8 @@ const ( loopThreshold = 60 * time.Second logFileAutoCloseDelay = 5 * time.Second logFileMaxOpenTime = time.Minute + panicUploadMaxWait = 30 * time.Second + panicUploadNoticeWait = 10 * time.Second ) func monitorMain(runtimeOptions RuntimeOptions) { @@ -72,6 +75,8 @@ func monitorMain(runtimeOptions RuntimeOptions) { childEnv := childEnv() first := true for { + maybeReportPanics() + if t := time.Since(restarts[0]); t < loopThreshold { l.Warnf("%d restarts in %v; not retrying further", countRestarts, t) os.Exit(exitError) @@ -173,6 +178,13 @@ func copyStderr(stderr io.Reader, dst io.Writer) { br := bufio.NewReader(stderr) var panicFd *os.File + defer func() { + if panicFd != nil { + _ = panicFd.Close() + maybeReportPanics() + } + }() + for { line, err := br.ReadString('\n') if err != nil { @@ -430,3 +442,39 @@ func childEnv() []string { env = append(env, "STMONITORED=yes") return env } + +// maybeReportPanics tries to figure out if crash reporting is on or off, +// and reports any panics it can find if it's enabled. We spend at most +// panicUploadMaxWait uploading panics... +func maybeReportPanics() { + // Try to get a config to see if/where panics should be reported. + cfg, err := loadOrDefaultConfig() + if err != nil { + l.Warnln("Couldn't load config; not reporting crash") + return + } + + // Bail if we're not supposed to report panics. + opts := cfg.Options() + if !opts.CREnabled { + return + } + + // Set up a timeout on the whole operation. + ctx, cancel := context.WithTimeout(context.Background(), panicUploadMaxWait) + defer cancel() + + // Print a notice if the upload takes a long time. + go func() { + select { + case <-ctx.Done(): + return + case <-time.After(panicUploadNoticeWait): + l.Warnln("Uploading crash reports is taking a while, please wait...") + } + }() + + // Report the panics. + dir := locations.GetBaseDir(locations.ConfigBaseDir) + uploadPanicLogs(ctx, opts.CRURL, dir) +} diff --git a/go.mod b/go.mod index f557a6f32..d255f8245 100644 --- a/go.mod +++ b/go.mod @@ -8,9 +8,11 @@ require ( github.com/calmh/du v1.0.1 github.com/calmh/xdr v1.1.0 github.com/ccding/go-stun v0.0.0-20180726100737-be486d185f3d + github.com/certifi/gocertifi v0.0.0-20190506164543-d2eda7129713 // indirect github.com/chmduquesne/rollinghash v0.0.0-20180912150627-a60f8e7142b5 github.com/d4l3k/messagediff v1.2.1 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 + github.com/getsentry/raven-go v0.2.0 github.com/gobwas/glob v0.0.0-20170212200151-51eb1ee00b6d github.com/gogo/protobuf v1.2.1 github.com/golang/groupcache v0.0.0-20171101203131-84a468cf14b4 @@ -20,6 +22,7 @@ require ( github.com/kr/pretty v0.1.0 // indirect github.com/lib/pq v1.1.1 github.com/lucas-clemente/quic-go v0.11.2 + github.com/maruel/panicparse v1.2.1 github.com/mattn/go-isatty v0.0.7 github.com/minio/sha256-simd v0.0.0-20190117184323-cc1980cb0338 github.com/oschwald/geoip2-golang v1.3.0 diff --git a/go.sum b/go.sum index 0ebc90cb2..c97071db3 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,8 @@ github.com/calmh/xdr v1.1.0 h1:U/Dd4CXNLoo8EiQ4ulJUXkgO1/EyQLgDKLgpY1SOoJE= github.com/calmh/xdr v1.1.0/go.mod h1:E8sz2ByAdXC8MbANf1LCRYzedSnnc+/sXXJs/PVqoeg= github.com/ccding/go-stun v0.0.0-20180726100737-be486d185f3d h1:As4937T5NVbJ/DmZT9z33pyLEprMd6CUSfhbmMY57Io= github.com/ccding/go-stun v0.0.0-20180726100737-be486d185f3d/go.mod h1:3FK1bMar37f7jqVY7q/63k3OMX1c47pGCufzt3X0sYE= +github.com/certifi/gocertifi v0.0.0-20190506164543-d2eda7129713 h1:UNOqI3EKhvbqV8f1Vm3NIwkrhq388sGCeAH2Op7w0rc= +github.com/certifi/gocertifi v0.0.0-20190506164543-d2eda7129713/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= @@ -34,6 +36,8 @@ github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWT github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -78,10 +82,15 @@ github.com/lucas-clemente/quic-go v0.11.2 h1:Mop0ac3zALaBR3wGs6j8OYe/tcFvFsxTUFM github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNAI4vA= github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= +github.com/maruel/panicparse v1.2.1 h1:mNlHGiakrixj+AwF/qRpTwnj+zsWYPRLQ7wRqnJsfO0= +github.com/maruel/panicparse v1.2.1/go.mod h1:vszMjr5QQ4F5FSRfraldcIA/BCw5xrdLL+zEcU2nRBs= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/minio/sha256-simd v0.0.0-20190117184323-cc1980cb0338 h1:USW1+zAUkUSvk097CAX/i8KR3r6f+DHNhk6Xe025Oyw= github.com/minio/sha256-simd v0.0.0-20190117184323-cc1980cb0338/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/gui/default/syncthing/core/notifications.html b/gui/default/syncthing/core/notifications.html index 7e523efac..4be6aab71 100644 --- a/gui/default/syncthing/core/notifications.html +++ b/gui/default/syncthing/core/notifications.html @@ -69,3 +69,50 @@ + + +
+
+

Automatic Crash Reporting

+
+
+

Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.

+

 Learn more

+
+ +
+
+ + +
+
+

Automatic Crash Reporting

+
+
+

Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.

+

However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.

+

 Learn more

+
+ +
+
diff --git a/gui/default/syncthing/core/syncthingController.js b/gui/default/syncthing/core/syncthingController.js index 8682627bf..ccd01ec8b 100755 --- a/gui/default/syncthing/core/syncthingController.js +++ b/gui/default/syncthing/core/syncthingController.js @@ -2426,4 +2426,9 @@ angular.module('syncthing.core') var err = status.error.replace(/.+: /, ''); return err + " (" + time + ")"; } + + $scope.setCrashReportingEnabled = function (enabled) { + $scope.config.options.crashReportingEnabled = enabled; + $scope.saveConfig(); + }; }); diff --git a/lib/config/config.go b/lib/config/config.go index 27777069e..e61798a56 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -29,7 +29,7 @@ import ( const ( OldestHandledVersion = 10 - CurrentVersion = 28 + CurrentVersion = 29 MaxRescanIntervalS = 365 * 24 * 60 * 60 ) diff --git a/lib/config/config_test.go b/lib/config/config_test.go index 283284091..cf7bf7a0c 100644 --- a/lib/config/config_test.go +++ b/lib/config/config_test.go @@ -69,6 +69,8 @@ func TestDefaultValues(t *testing.T) { UnackedNotificationIDs: []string{}, DefaultFolderPath: "~", SetLowPriority: true, + CRURL: "https://crash.syncthing.net/newcrash", + CREnabled: true, StunKeepaliveStartS: 180, StunKeepaliveMinS: 20, StunServers: []string{"default"}, @@ -203,7 +205,8 @@ func TestOverriddenValues(t *testing.T) { ProgressUpdateIntervalS: 10, LimitBandwidthInLan: true, MinHomeDiskFree: Size{5.2, "%"}, - URSeen: 2, + URSeen: 8, + URAccepted: 4, URURL: "https://localhost/newdata", URInitialDelayS: 800, URPostInsecurely: true, @@ -211,15 +214,14 @@ func TestOverriddenValues(t *testing.T) { AlwaysLocalNets: []string{}, OverwriteRemoteDevNames: true, TempIndexMinBlocks: 100, - UnackedNotificationIDs: []string{ - "channelNotification", // added in 17->18 migration - "fsWatcherNotification", // added in 27->28 migration - }, - DefaultFolderPath: "/media/syncthing", - SetLowPriority: false, - StunKeepaliveStartS: 9000, - StunKeepaliveMinS: 900, - StunServers: []string{"foo"}, + UnackedNotificationIDs: []string{"asdfasdf"}, + DefaultFolderPath: "/media/syncthing", + SetLowPriority: false, + CRURL: "https://localhost/newcrash", + CREnabled: false, + StunKeepaliveStartS: 9000, + StunKeepaliveMinS: 900, + StunServers: []string{"foo"}, } os.Unsetenv("STNOUPGRADE") diff --git a/lib/config/migrations.go b/lib/config/migrations.go index 2987fd672..c2d0e9fb4 100644 --- a/lib/config/migrations.go +++ b/lib/config/migrations.go @@ -25,6 +25,7 @@ import ( // update the config version. The order of migrations doesn't matter here, // put the newest on top for readability. var migrations = migrationSet{ + {29, migrateToConfigV29}, {28, migrateToConfigV28}, {27, migrateToConfigV27}, {26, nil}, // triggers database update @@ -83,6 +84,19 @@ func (m migration) apply(cfg *Configuration) { cfg.Version = m.targetVersion } +func migrateToConfigV29(cfg *Configuration) { + // The new crash reporting option should follow the state of global + // discovery / usage reporting, and we should display an appropriate + // notification. + if cfg.Options.GlobalAnnEnabled || cfg.Options.URAccepted > 0 { + cfg.Options.CREnabled = true + cfg.Options.UnackedNotificationIDs = append(cfg.Options.UnackedNotificationIDs, "crAutoEnabled") + } else { + cfg.Options.CREnabled = false + cfg.Options.UnackedNotificationIDs = append(cfg.Options.UnackedNotificationIDs, "crAutoDisabled") + } +} + func migrateToConfigV28(cfg *Configuration) { // Show a notification about enabling filesystem watching cfg.Options.UnackedNotificationIDs = append(cfg.Options.UnackedNotificationIDs, "fsWatcherNotification") diff --git a/lib/config/migrations_test.go b/lib/config/migrations_test.go new file mode 100644 index 000000000..e8e43faed --- /dev/null +++ b/lib/config/migrations_test.go @@ -0,0 +1,34 @@ +// Copyright (C) 2019 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +package config + +import "testing" + +func TestMigrateCrashReporting(t *testing.T) { + // When migrating from pre-crash-reporting configs, crash reporting is + // enabled if global discovery is enabled or if usage reporting is + // enabled (not just undecided). + cases := []struct { + opts OptionsConfiguration + enabled bool + }{ + {opts: OptionsConfiguration{URAccepted: 0, GlobalAnnEnabled: true}, enabled: true}, + {opts: OptionsConfiguration{URAccepted: -1, GlobalAnnEnabled: true}, enabled: true}, + {opts: OptionsConfiguration{URAccepted: 1, GlobalAnnEnabled: true}, enabled: true}, + {opts: OptionsConfiguration{URAccepted: 0, GlobalAnnEnabled: false}, enabled: false}, + {opts: OptionsConfiguration{URAccepted: -1, GlobalAnnEnabled: false}, enabled: false}, + {opts: OptionsConfiguration{URAccepted: 1, GlobalAnnEnabled: false}, enabled: true}, + } + + for i, tc := range cases { + cfg := Configuration{Version: 28, Options: tc.opts} + migrations.apply(&cfg) + if cfg.Options.CREnabled != tc.enabled { + t.Errorf("%d: unexpected result, CREnabled: %v != %v", i, cfg.Options.CREnabled, tc.enabled) + } + } +} diff --git a/lib/config/optionsconfiguration.go b/lib/config/optionsconfiguration.go index e4da60481..d52f2ccfb 100644 --- a/lib/config/optionsconfiguration.go +++ b/lib/config/optionsconfiguration.go @@ -29,11 +29,11 @@ type OptionsConfiguration struct { NATLeaseM int `xml:"natLeaseMinutes" json:"natLeaseMinutes" default:"60"` NATRenewalM int `xml:"natRenewalMinutes" json:"natRenewalMinutes" default:"30"` NATTimeoutS int `xml:"natTimeoutSeconds" json:"natTimeoutSeconds" default:"10"` - URAccepted int `xml:"urAccepted" json:"urAccepted"` // Accepted usage reporting version; 0 for off (undecided), -1 for off (permanently) - URSeen int `xml:"urSeen" json:"urSeen"` // Report which the user has been prompted for. - URUniqueID string `xml:"urUniqueID" json:"urUniqueId"` // Unique ID for reporting purposes, regenerated when UR is turned on. - URURL string `xml:"urURL" json:"urURL" default:"https://data.syncthing.net/newdata"` - URPostInsecurely bool `xml:"urPostInsecurely" json:"urPostInsecurely" default:"false"` // For testing + URAccepted int `xml:"urAccepted" json:"urAccepted"` // Accepted usage reporting version; 0 for off (undecided), -1 for off (permanently) + URSeen int `xml:"urSeen" json:"urSeen"` // Report which the user has been prompted for. + URUniqueID string `xml:"urUniqueID" json:"urUniqueId"` // Unique ID for reporting purposes, regenerated when UR is turned on. + URURL string `xml:"urURL" json:"urURL" default:"https://data.syncthing.net/newdata"` // usage reporting URL + URPostInsecurely bool `xml:"urPostInsecurely" json:"urPostInsecurely" default:"false"` // For testing URInitialDelayS int `xml:"urInitialDelayS" json:"urInitialDelayS" default:"1800"` RestartOnWakeup bool `xml:"restartOnWakeup" json:"restartOnWakeup" default:"true" restart:"true"` AutoUpgradeIntervalH int `xml:"autoUpgradeIntervalH" json:"autoUpgradeIntervalH" default:"12" restart:"true"` // 0 for off @@ -52,6 +52,8 @@ type OptionsConfiguration struct { DefaultFolderPath string `xml:"defaultFolderPath" json:"defaultFolderPath" default:"~"` SetLowPriority bool `xml:"setLowPriority" json:"setLowPriority" default:"true"` MaxConcurrentScans int `xml:"maxConcurrentScans" json:"maxConcurrentScans"` + CRURL string `xml:"crashReportingURL" json:"crURL" default:"https://crash.syncthing.net/newcrash"` // crash reporting URL + CREnabled bool `xml:"crashReportingEnabled" json:"crashReportingEnabled" default:"true" restart:"true"` StunKeepaliveStartS int `xml:"stunKeepaliveStartS" json:"stunKeepaliveStartS" default:"180"` // 0 for off StunKeepaliveMinS int `xml:"stunKeepaliveMinS" json:"stunKeepaliveMinS" default:"20"` // 0 for off StunServers []string `xml:"stunServer" json:"stunServers" default:"default"` diff --git a/lib/config/testdata/overridenvalues.xml b/lib/config/testdata/overridenvalues.xml index 9e3836d36..9d50b5e7a 100644 --- a/lib/config/testdata/overridenvalues.xml +++ b/lib/config/testdata/overridenvalues.xml @@ -1,4 +1,4 @@ - + tcp://:23000 false @@ -27,8 +27,10 @@ false true 42 - 5.2 + 5.2 https://localhost/newdata + 8 + 4 800 true https://localhost/releases @@ -36,8 +38,11 @@ 100 /media/syncthing false + https://localhost/newcrash + false 9000 900 foo + asdfasdf diff --git a/lib/config/testdata/v29.xml b/lib/config/testdata/v29.xml new file mode 100644 index 000000000..231cd882c --- /dev/null +++ b/lib/config/testdata/v29.xml @@ -0,0 +1,16 @@ + + + basic + + + 1 + -1 + true + + +
tcp://a
+
+ +
tcp://b
+
+
diff --git a/lib/ur/usage_report.go b/lib/ur/usage_report.go index 703b7be5a..643d08c20 100644 --- a/lib/ur/usage_report.go +++ b/lib/ur/usage_report.go @@ -66,7 +66,8 @@ func New(cfg config.Wrapper, m model.Model, connectionsService connections.Servi // ReportData returns the data to be sent in a usage report with the currently // configured usage reporting version. func (s *Service) ReportData() map[string]interface{} { - return s.reportData(Version, false) + urVersion := s.cfg.Options().URAccepted + return s.reportData(urVersion, false) } // ReportDataPreview returns a preview of the data to be sent in a usage report