frankenphp
frankenphp copied to clipboard
Adds basic file watcher
This PR adds a basic version of a file watcher to reload workers when changing files. The watcher is based on github.com/fsnotify/fsnotify since it's already a downstream dependency of the caddfy module.
Some notes:
- fsnotify doesn't yet officially support recursive watching, so the watcher.go implements it itself via
filepath.Walk - The watcher also supports file patterns, the following is valid:
{
frankenphp {
watch /path/to/app/folder1 # watches all subdirectories
watch /path/to/app/folder2/*.php # watches only php files in the app directory
watch /path/to/app/folder3/**/*.php # watches only php files in the app directory and subdirectories
}
}
- if a worker gets stuck in a request, the watcher will wait for the worker to finish before performing another reload (don't know if there's a better way to do this)
- I wasn't quite sure how to best test the watcher integration. There seems to be a race condition that sometimes makes the
watcher_test.gofail, which I don't yet quite understand (it's related to theworkersReadyWG) - I'm still learning go, so the implementation might not be ideal 😊
Actually the test needs to create a file while running in the pipeline (to trigger the file watcher), but it looks like it's not allowed to do so due to permissions.
Hi @AlliBalliBaba,
thank you very much for working on this feature! This is a must-have.
I also started the work on my side and created https://github.com/dunglas/go-fswatch for this purpose some weeks ago.
My bindings rely on cgo, but as we need cgo anyway, I don't think that's an issue. The benefits of the C/C++ fswatch library is that it has more features (including recursive watchers) and supports more platforms.
Would you consider switching to this library?
Hey yeah, I'll try swapping to https://github.com/dunglas/go-fswatch, having recursive watching out of the box is great!
I switched to your watcher and it works great 👍 Some questions @dunglas :
- I installed
fswatchfrom the tar in thedev.Dockerfileand tests are running locally. Not sure of all the other places where it would need to be installed - I saw that the library allows regex as filters, does it also allow a wildcard pattern? Wild card patterns are probably more user-friendly, it would allow removing the logic I currently implemented via
filepath.Match
Awesome!!
In addition to dev.Dockerfile, we'll have to compile the dynamic library in the builder stage of the Dockerfile and alpine.Dockerfile and to copy the .so in the runner stage.
We'll also avec to modify build-static.sh to compile the lib statically. (I'm not sure exactly how)
I can do this part when I'll have some time (likely after the API Platform Conference) if you want.
Regarding wildcards (globs?), I don't think that it's natively supported, but regexp are more powerful anyway.
My idea was to let users define custom regexp, but defaults to a regexp that will work for standard installations of Laravel and Symfony (and maybe other popular projects such as WordPress and Drupal) so most users will not have to figure out the regexp (or the glob) by themselves. WDYT about this approach?
So I tried installing fswatch in the Dockerfiles and it works for debian, but alpine throws a dependency error
Error loading shared library libstdc++.so.6: No such file or directory
During testing I also noticed that there will sometimes be a segfault with low watcher latencies (<100ms)
expand
go test SIGSEGV: segmentation violation PC=0x7f2666817f9b m=5 sigcode=2 addr=0x7f263c000ef4 signal arrived during cgo executiongoroutine 7103 gp=0xc000510c40 m=5 mp=0xc000100008 [syscall]: runtime.cgocall(0x790d60, 0xc0115e5778) /usr/local/go/src/runtime/cgocall.go:157 +0x4b fp=0xc0115e5750 sp=0xc0115e5718 pc=0x408d2b github.com/dunglas/go-fswatch._Cfunc_fsw_start_monitor(0x7f2514000b70) _cgo_gotypes.go:345 +0x47 fp=0xc0115e5778 sp=0xc0115e5750 pc=0x71eca7 github.com/dunglas/frankenphp.initWatcher.gowrap1.(*Session).Start.1(0xc0115e57d0?) /go/pkg/mod/github.com/dunglas/[email protected]/fswatch.go:32 +0x3e fp=0xc0115e57b8 sp=0xc0115e5778 pc=0x76105e github.com/dunglas/go-fswatch.(*Session).Start(...) /go/pkg/mod/github.com/dunglas/[email protected]/fswatch.go:32 github.com/dunglas/frankenphp.initWatcher.gowrap1() /go/src/app/watcher.go:32 +0x25 fp=0xc0115e57e0 sp=0xc0115e57b8 pc=0x760fe5 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0115e57e8 sp=0xc0115e57e0 pc=0x478ac1 created by github.com/dunglas/frankenphp.initWatcher in goroutine 7368 /go/src/app/watcher.go:32 +0x95
goroutine 1 gp=0xc0000061c0 m=nil [chan receive]: runtime.gopark(0xc000c88750?, 0xc000c887d8?, 0x50?, 0x87?, 0x7ebac0?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0000f59c0 sp=0xc0000f59a0 pc=0x44198e runtime.chanrecv(0xc011bb6000, 0xc0000f5aa7, 0x1) /usr/local/go/src/runtime/chan.go:583 +0x3bf fp=0xc0000f5a38 sp=0xc0000f59c0 pc=0x40b3bf runtime.chanrecv1(0xb83240?, 0x7bf8c0?) /usr/local/go/src/runtime/chan.go:442 +0x12 fp=0xc0000f5a60 sp=0xc0000f5a38 pc=0x40aff2 testing.(*T).Run(0xc0000d8680, {0x85fe33?, 0x0?}, 0x8869c0) /usr/local/go/src/testing/testing.go:1750 +0x3ab fp=0xc0000f5b20 sp=0xc0000f5a60 pc=0x50b0cb testing.runTests.func1(0xc0000d8680) /usr/local/go/src/testing/testing.go:2161 +0x37 fp=0xc0000f5b60 sp=0xc0000f5b20 pc=0x50d217 testing.tRunner(0xc0000d8680, 0xc000035c70) /usr/local/go/src/testing/testing.go:1689 +0xfb fp=0xc0000f5bb0 sp=0xc0000f5b60 pc=0x50a1fb testing.runTests(0xc000012dc8, {0xb44280, 0x41, 0x41}, {0x1?, 0x4e98ee?, 0xb83b20?}) /usr/local/go/src/testing/testing.go:2159 +0x445 fp=0xc0000f5ca0 sp=0xc0000f5bb0 pc=0x50d105 testing.(*M).Run(0xc00003b360) /usr/local/go/src/testing/testing.go:2027 +0x68b fp=0xc0000f5ed0 sp=0xc0000f5ca0 pc=0x50bb0b main.main() _testmain.go:183 +0x16c fp=0xc0000f5f50 sp=0xc0000f5ed0 pc=0x78e4ac runtime.main() /usr/local/go/src/runtime/proc.go:271 +0x29d fp=0xc0000f5fe0 sp=0xc0000f5f50 pc=0x44153d runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0000f5fe8 sp=0xc0000f5fe0 pc=0x478ac1
goroutine 2 gp=0xc000006c40 m=nil [force gc (idle)]: runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc00007afa8 sp=0xc00007af88 pc=0x44198e runtime.goparkunlock(...) /usr/local/go/src/runtime/proc.go:408 runtime.forcegchelper() /usr/local/go/src/runtime/proc.go:326 +0xb3 fp=0xc00007afe0 sp=0xc00007afa8 pc=0x4417f3 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc00007afe8 sp=0xc00007afe0 pc=0x478ac1 created by runtime.init.6 in goroutine 1 /usr/local/go/src/runtime/proc.go:314 +0x1a
goroutine 3 gp=0xc000007180 m=nil [GC sweep wait]: runtime.gopark(0xb83201?, 0x0?, 0x0?, 0x0?, 0x0?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc00007b780 sp=0xc00007b760 pc=0x44198e runtime.goparkunlock(...) /usr/local/go/src/runtime/proc.go:408 runtime.bgsweep(0xc00002e070) /usr/local/go/src/runtime/mgcsweep.go:318 +0xdf fp=0xc00007b7c8 sp=0xc00007b780 pc=0x42ab3f runtime.gcenable.gowrap1() /usr/local/go/src/runtime/mgc.go:203 +0x25 fp=0xc00007b7e0 sp=0xc00007b7c8 pc=0x41f445 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc00007b7e8 sp=0xc00007b7e0 pc=0x478ac1 created by runtime.gcenable in goroutine 1 /usr/local/go/src/runtime/mgc.go:203 +0x66
goroutine 4 gp=0xc000007340 m=nil [GC scavenge wait]: runtime.gopark(0x10000?, 0x5d91fb?, 0x0?, 0x0?, 0x0?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc00007bf78 sp=0xc00007bf58 pc=0x44198e runtime.goparkunlock(...) /usr/local/go/src/runtime/proc.go:408 runtime.(*scavengerState).park(0xb83cc0) /usr/local/go/src/runtime/mgcscavenge.go:425 +0x49 fp=0xc00007bfa8 sp=0xc00007bf78 pc=0x4284e9 runtime.bgscavenge(0xc00002e070) /usr/local/go/src/runtime/mgcscavenge.go:658 +0x59 fp=0xc00007bfc8 sp=0xc00007bfa8 pc=0x428a99 runtime.gcenable.gowrap2() /usr/local/go/src/runtime/mgc.go:204 +0x25 fp=0xc00007bfe0 sp=0xc00007bfc8 pc=0x41f3e5 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc00007bfe8 sp=0xc00007bfe0 pc=0x478ac1 created by runtime.gcenable in goroutine 1 /usr/local/go/src/runtime/mgc.go:204 +0xa5
goroutine 5 gp=0xc000007c00 m=nil [finalizer wait]: runtime.gopark(0x0?, 0x886b30?, 0x0?, 0x40?, 0x1000000010?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc00007a620 sp=0xc00007a600 pc=0x44198e runtime.runfinq() /usr/local/go/src/runtime/mfinal.go:194 +0x107 fp=0xc00007a7e0 sp=0xc00007a620 pc=0x41e487 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc00007a7e8 sp=0xc00007a7e0 pc=0x478ac1 created by runtime.createfing in goroutine 1 /usr/local/go/src/runtime/mfinal.go:164 +0x3d
goroutine 6 gp=0xc0001861c0 m=nil [sync.Cond.Wait]: runtime.gopark(0x774942?, 0xc00007c628?, 0x4?, 0x42?, 0xc000892100?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc00007c5f8 sp=0xc00007c5d8 pc=0x44198e runtime.goparkunlock(...) /usr/local/go/src/runtime/proc.go:408 sync.runtime_notifyListWait(0xc0000000d8, 0x4) /usr/local/go/src/runtime/sema.go:569 +0x159 fp=0xc00007c648 sp=0xc00007c5f8 pc=0x474f39 sync.(*Cond).Wait(0xc00007c710?) /usr/local/go/src/sync/cond.go:70 +0x85 fp=0xc00007c688 sp=0xc00007c648 pc=0x4807c5 github.com/maypok86/otter/internal/queue.(*Growable[...]).Pop(0x8fa440) /go/pkg/mod/github.com/maypok86/[email protected]/internal/queue/growable.go:71 +0x74 fp=0xc00007c720 sp=0xc00007c688 pc=0x7728d4 github.com/maypok86/otter/internal/core.(*Cache[...]).process(0x8ffa20) /go/pkg/mod/github.com/maypok86/[email protected]/internal/core/cache.go:454 +0x4d fp=0xc00007c7c0 sp=0xc00007c720 pc=0x7712cd github.com/maypok86/otter/internal/core.NewCache[...].gowrap2() /go/pkg/mod/github.com/maypok86/[email protected]/internal/core/cache.go:188 +0x25 fp=0xc00007c7e0 sp=0xc00007c7c0 pc=0x76a845 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc00007c7e8 sp=0xc00007c7e0 pc=0x478ac1 created by github.com/maypok86/otter/internal/core.NewCache[...] in goroutine 1 /go/pkg/mod/github.com/maypok86/[email protected]/internal/core/cache.go:188 +0x837
goroutine 220 gp=0xc000186a80 m=nil [GC worker (idle)]: runtime.gopark(0xc0000d9a00?, 0x0?, 0x0?, 0x0?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001c7750 sp=0xc0001c7730 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001c77e0 sp=0xc0001c7750 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001c77e8 sp=0xc0001c77e0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 273 gp=0xc000187dc0 m=nil [GC worker (idle)]: runtime.gopark(0x28c636a37dca?, 0x1?, 0xe2?, 0x76?, 0x0?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001f3750 sp=0xc0001f3730 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001f37e0 sp=0xc0001f3750 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001f37e8 sp=0xc0001f37e0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 271 gp=0xc0001c2000 m=nil [GC worker (idle)]: runtime.gopark(0x28c5fc4e3c5b?, 0x1?, 0x5a?, 0xab?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001f2750 sp=0xc0001f2730 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001f27e0 sp=0xc0001f2750 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001f27e8 sp=0xc0001f27e0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 272 gp=0xc0001c21c0 m=nil [GC worker (idle)]: runtime.gopark(0xbe61a0?, 0x1?, 0xa2?, 0x9b?, 0x0?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001f2f50 sp=0xc0001f2f30 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001f2fe0 sp=0xc0001f2f50 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001f2fe8 sp=0xc0001f2fe0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 270 gp=0xc0001c2380 m=nil [GC worker (idle)]: runtime.gopark(0xbe61a0?, 0x1?, 0x97?, 0x80?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001f5f50 sp=0xc0001f5f30 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001f5fe0 sp=0xc0001f5f50 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001f5fe8 sp=0xc0001f5fe0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 268 gp=0xc0001c2540 m=nil [GC worker (idle)]: runtime.gopark(0xc0000d9a00?, 0x0?, 0x0?, 0x0?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001d5f50 sp=0xc0001d5f30 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001d5fe0 sp=0xc0001d5f50 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001d5fe8 sp=0xc0001d5fe0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 267 gp=0xc0001c2700 m=nil [GC worker (idle)]: runtime.gopark(0xc0000d9a00?, 0x0?, 0x0?, 0x0?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001d6750 sp=0xc0001d6730 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001d67e0 sp=0xc0001d6750 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001d67e8 sp=0xc0001d67e0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 219 gp=0xc0001c2fc0 m=nil [GC worker (idle)]: runtime.gopark(0xc0000d9a00?, 0x0?, 0x0?, 0x0?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001c6f50 sp=0xc0001c6f30 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001c6fe0 sp=0xc0001c6f50 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001c6fe8 sp=0xc0001c6fe0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 221 gp=0xc0001c3340 m=nil [GC worker (idle)]: runtime.gopark(0x28c5e3c5d482?, 0x1?, 0xe8?, 0xcc?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001c7f50 sp=0xc0001c7f30 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001c7fe0 sp=0xc0001c7f50 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001c7fe8 sp=0xc0001c7fe0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 269 gp=0xc0001cea80 m=nil [GC worker (idle)]: runtime.gopark(0x28c6371f3c61?, 0x1?, 0xb1?, 0x9d?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001d2750 sp=0xc0001d2730 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001d27e0 sp=0xc0001d2750 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001d27e8 sp=0xc0001d27e0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 218 gp=0xc0001cf340 m=nil [GC worker (idle)]: runtime.gopark(0xc0000d9a00?, 0x0?, 0x0?, 0x0?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001c6750 sp=0xc0001c6730 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001c67e0 sp=0xc0001c6750 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001c67e8 sp=0xc0001c67e0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 223 gp=0xc0001cfc00 m=nil [GC worker (idle)]: runtime.gopark(0x28c603ab12e0?, 0x1?, 0x3c?, 0x30?, 0x0?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001caf50 sp=0xc0001caf30 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001cafe0 sp=0xc0001caf50 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001cafe8 sp=0xc0001cafe0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 235 gp=0xc0001d88c0 m=nil [GC worker (idle)]: runtime.gopark(0xc0000d9a00?, 0x0?, 0x0?, 0x0?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001e8750 sp=0xc0001e8730 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001e87e0 sp=0xc0001e8750 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001e87e8 sp=0xc0001e87e0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 254 gp=0xc0001d8a80 m=nil [GC worker (idle)]: runtime.gopark(0x28c636a37d6f?, 0x1?, 0xd7?, 0x4c?, 0x0?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001d7f50 sp=0xc0001d7f30 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001d7fe0 sp=0xc0001d7f50 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001d7fe8 sp=0xc0001d7fe0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 252 gp=0xc0001d8c40 m=nil [GC worker (idle)]: runtime.gopark(0xc0000d9a00?, 0x0?, 0x0?, 0x0?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001d0f50 sp=0xc0001d0f30 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001d0fe0 sp=0xc0001d0f50 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001d0fe8 sp=0xc0001d0fe0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 255 gp=0xc0001d9180 m=nil [GC worker (idle)]: runtime.gopark(0x28c5e799f9ad?, 0x1?, 0x7a?, 0x63?, 0x0?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001d6f50 sp=0xc0001d6f30 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001d6fe0 sp=0xc0001d6f50 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001d6fe8 sp=0xc0001d6fe0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 251 gp=0xc0001d9a40 m=nil [GC worker (idle)]: runtime.gopark(0xc0000d9a00?, 0x0?, 0x0?, 0x0?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001dbf50 sp=0xc0001dbf30 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001dbfe0 sp=0xc0001dbf50 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001dbfe8 sp=0xc0001dbfe0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 253 gp=0xc0001e2c40 m=nil [GC worker (idle)]: runtime.gopark(0x28c636a37e71?, 0x1?, 0x24?, 0xd?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001d0750 sp=0xc0001d0730 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001d07e0 sp=0xc0001d0750 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001d07e8 sp=0xc0001d07e0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 222 gp=0xc0001ece00 m=nil [GC worker (idle)]: runtime.gopark(0x28c6033ba561?, 0x1?, 0x75?, 0x14?, 0x0?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001ca750 sp=0xc0001ca730 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001ca7e0 sp=0xc0001ca750 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001ca7e8 sp=0xc0001ca7e0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 224 gp=0xc0001ed500 m=nil [GC worker (idle)]: runtime.gopark(0x28c604f96015?, 0x1?, 0x1d?, 0xdd?, 0x7bfb00?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0001cb750 sp=0xc0001cb730 pc=0x44198e runtime.gcBgMarkWorker() /usr/local/go/src/runtime/mgc.go:1310 +0xe5 fp=0xc0001cb7e0 sp=0xc0001cb750 pc=0x421525 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0001cb7e8 sp=0xc0001cb7e0 pc=0x478ac1 created by runtime.gcBgMarkStartWorkers in goroutine 138 /usr/local/go/src/runtime/mgc.go:1234 +0x1c
goroutine 132 gp=0xc0004028c0 m=nil [select, locked to thread]:
runtime.gopark(0xc000253e08?, 0x2?, 0x60?, 0x98?, 0xc000253dcc?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc000253c60 sp=0xc000253c40 pc=0x44198e
runtime.selectgo(0xc000253e08, 0xc000253dc8, 0x0?, 0x0, 0xc0004028c0?, 0x1)
/usr/local/go/src/runtime/select.go:327 +0x725 fp=0xc000253d80 sp=0xc000253c60 pc=0x453725
github.com/dunglas/frankenphp.go_handle_request()
/go/src/app/frankenphp.go:474 +0x9b fp=0xc000253e48 sp=0xc000253d80 pc=0x765efb
_cgoexp_a4e4414eb6e0_go_handle_request(0x7f25ec7f7d2f)
_cgo_gotypes.go:916 +0x14 fp=0xc000253e58 sp=0xc000253e48 pc=0x76b114
runtime.cgocallbackg1(0x76b100, 0x7f25ec7f7d2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:420 +0x2a5 fp=0xc000253f18 sp=0xc000253e58 pc=0x409485
runtime.cgocallbackg(0x76b100, 0x7f25ec7f7d2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:339 +0x136 fp=0xc000253f90 sp=0xc000253f18 pc=0x409136
runtime.cgocallbackg(0x76b100, 0x7f25ec7f7d2f, 0x0)
goroutine 190 gp=0xc000273500 m=nil [select, locked to thread]:
runtime.gopark(0xc00012be08?, 0x2?, 0x60?, 0x15?, 0xc00012bdcc?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc00012bc60 sp=0xc00012bc40 pc=0x44198e
runtime.selectgo(0xc00012be08, 0xc00012bdc8, 0x0?, 0x0, 0xc000273500?, 0x1)
/usr/local/go/src/runtime/select.go:327 +0x725 fp=0xc00012bd80 sp=0xc00012bc60 pc=0x453725
github.com/dunglas/frankenphp.go_handle_request()
/go/src/app/frankenphp.go:474 +0x9b fp=0xc00012be48 sp=0xc00012bd80 pc=0x765efb
_cgoexp_a4e4414eb6e0_go_handle_request(0x7f25f8ff8d2f)
_cgo_gotypes.go:916 +0x14 fp=0xc00012be58 sp=0xc00012be48 pc=0x76b114
runtime.cgocallbackg1(0x76b100, 0x7f25f8ff8d2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:420 +0x2a5 fp=0xc00012bf18 sp=0xc00012be58 pc=0x409485
runtime.cgocallbackg(0x76b100, 0x7f25f8ff8d2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:339 +0x136 fp=0xc00012bf90 sp=0xc00012bf18 pc=0x409136
runtime.cgocallbackg(0x76b100, 0x7f25f8ff8d2f, 0x0)
goroutine 198 gp=0xc00064cfc0 m=nil [select, locked to thread]:
runtime.gopark(0xc000db3e08?, 0x2?, 0xe0?, 0x44?, 0xc000db3dcc?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc000db3c60 sp=0xc000db3c40 pc=0x44198e
runtime.selectgo(0xc000db3e08, 0xc000db3dc8, 0x0?, 0x0, 0xc00064cfc0?, 0x1)
/usr/local/go/src/runtime/select.go:327 +0x725 fp=0xc000db3d80 sp=0xc000db3c60 pc=0x453725
github.com/dunglas/frankenphp.go_handle_request()
/go/src/app/frankenphp.go:474 +0x9b fp=0xc000db3e48 sp=0xc000db3d80 pc=0x765efb
_cgoexp_a4e4414eb6e0_go_handle_request(0x7f25f9ffad2f)
_cgo_gotypes.go:916 +0x14 fp=0xc000db3e58 sp=0xc000db3e48 pc=0x76b114
runtime.cgocallbackg1(0x76b100, 0x7f25f9ffad2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:420 +0x2a5 fp=0xc000db3f18 sp=0xc000db3e58 pc=0x409485
runtime.cgocallbackg(0x76b100, 0x7f25f9ffad2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:339 +0x136 fp=0xc000db3f90 sp=0xc000db3f18 pc=0x409136
runtime.cgocallbackg(0x76b100, 0x7f25f9ffad2f, 0x0)
goroutine 199 gp=0xc00064d6c0 m=nil [select, locked to thread]:
runtime.gopark(0xc000525e08?, 0x2?, 0x20?, 0x24?, 0xc000525dcc?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc000525c60 sp=0xc000525c40 pc=0x44198e
runtime.selectgo(0xc000525e08, 0xc000525dc8, 0x0?, 0x0, 0xc00064d6c0?, 0x1)
/usr/local/go/src/runtime/select.go:327 +0x725 fp=0xc000525d80 sp=0xc000525c60 pc=0x453725
github.com/dunglas/frankenphp.go_handle_request()
/go/src/app/frankenphp.go:474 +0x9b fp=0xc000525e48 sp=0xc000525d80 pc=0x765efb
_cgoexp_a4e4414eb6e0_go_handle_request(0x7f25f97f9d2f)
_cgo_gotypes.go:916 +0x14 fp=0xc000525e58 sp=0xc000525e48 pc=0x76b114
runtime.cgocallbackg1(0x76b100, 0x7f25f97f9d2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:420 +0x2a5 fp=0xc000525f18 sp=0xc000525e58 pc=0x409485
runtime.cgocallbackg(0x76b100, 0x7f25f97f9d2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:339 +0x136 fp=0xc000525f90 sp=0xc000525f18 pc=0x409136
runtime.cgocallbackg(0x76b100, 0x7f25f97f9d2f, 0x0)
goroutine 203 gp=0xc00067f340 m=nil [select, locked to thread]:
runtime.gopark(0xc000ae1e08?, 0x2?, 0xc0?, 0x12?, 0xc000ae1dcc?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc000ae1c60 sp=0xc000ae1c40 pc=0x44198e
runtime.selectgo(0xc000ae1e08, 0xc000ae1dc8, 0x0?, 0x0, 0xc00067f340?, 0x1)
/usr/local/go/src/runtime/select.go:327 +0x725 fp=0xc000ae1d80 sp=0xc000ae1c60 pc=0x453725
github.com/dunglas/frankenphp.go_handle_request()
/go/src/app/frankenphp.go:474 +0x9b fp=0xc000ae1e48 sp=0xc000ae1d80 pc=0x765efb
_cgoexp_a4e4414eb6e0_go_handle_request(0x7f25efffed2f)
_cgo_gotypes.go:916 +0x14 fp=0xc000ae1e58 sp=0xc000ae1e48 pc=0x76b114
runtime.cgocallbackg1(0x76b100, 0x7f25efffed2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:420 +0x2a5 fp=0xc000ae1f18 sp=0xc000ae1e58 pc=0x409485
runtime.cgocallbackg(0x76b100, 0x7f25efffed2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:339 +0x136 fp=0xc000ae1f90 sp=0xc000ae1f18 pc=0x409136
runtime.cgocallbackg(0x76b100, 0x7f25efffed2f, 0x0)
goroutine 206 gp=0xc000760700 m=nil [select, locked to thread]:
runtime.gopark(0xc011b87e08?, 0x2?, 0xe0?, 0xf0?, 0xc011b87dcc?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc011b87c60 sp=0xc011b87c40 pc=0x44198e
runtime.selectgo(0xc011b87e08, 0xc011b87dc8, 0x0?, 0x0, 0xc000760700?, 0x1)
/usr/local/go/src/runtime/select.go:327 +0x725 fp=0xc011b87d80 sp=0xc011b87c60 pc=0x453725
github.com/dunglas/frankenphp.go_handle_request()
/go/src/app/frankenphp.go:474 +0x9b fp=0xc011b87e48 sp=0xc011b87d80 pc=0x765efb
_cgoexp_a4e4414eb6e0_go_handle_request(0x7f2618e0ed2f)
_cgo_gotypes.go:916 +0x14 fp=0xc011b87e58 sp=0xc011b87e48 pc=0x76b114
runtime.cgocallbackg1(0x76b100, 0x7f2618e0ed2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:420 +0x2a5 fp=0xc011b87f18 sp=0xc011b87e58 pc=0x409485
runtime.cgocallbackg(0x76b100, 0x7f2618e0ed2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:339 +0x136 fp=0xc011b87f90 sp=0xc011b87f18 pc=0x409136
runtime.cgocallbackg(0x76b100, 0x7f2618e0ed2f, 0x0)
goroutine 208 gp=0xc000511180 m=nil [select, locked to thread]:
runtime.gopark(0xc00011faf8?, 0x2?, 0x0?, 0x0?, 0xc00011f89c?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc00011f738 sp=0xc00011f718 pc=0x44198e
runtime.selectgo(0xc00011faf8, 0xc00011f898, 0x1?, 0x0, 0xc00011fa08?, 0x1)
/usr/local/go/src/runtime/select.go:327 +0x725 fp=0xc00011f858 sp=0xc00011f738 pc=0x453725
github.com/dunglas/frankenphp.go_frankenphp_worker_handle_request_start(0x2e42)
/go/src/app/worker.go:173 +0x293 fp=0xc00011fb70 sp=0xc00011f858 pc=0x769a73
_cgoexp_a4e4414eb6e0_go_frankenphp_worker_handle_request_start(0x7f25affb53c0)
_cgo_gotypes.go:1023 +0x1e fp=0xc00011fb88 sp=0xc00011fb70 pc=0x76b49e
runtime.cgocallbackg1(0x76b480, 0x7f25affb53c0, 0x0)
/usr/local/go/src/runtime/cgocall.go:420 +0x2a5 fp=0xc00011fc48 sp=0xc00011fb88 pc=0x409485
runtime.cgocallbackg(0x76b480, 0x7f25affb53c0, 0x0)
/usr/local/go/src/runtime/cgocall.go:339 +0x136 fp=0xc00011fcc0 sp=0xc00011fc48 pc=0x409136
runtime.cgocallbackg(0x76b480, 0x7f25affb53c0, 0x0)
goroutine 211 gp=0xc000562700 m=nil [select, locked to thread]:
runtime.gopark(0xc0008d1e08?, 0x2?, 0x80?, 0xfc?, 0xc0008d1dcc?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0008d1c60 sp=0xc0008d1c40 pc=0x44198e
runtime.selectgo(0xc0008d1e08, 0xc0008d1dc8, 0x0?, 0x0, 0xc000562700?, 0x1)
/usr/local/go/src/runtime/select.go:327 +0x725 fp=0xc0008d1d80 sp=0xc0008d1c60 pc=0x453725
github.com/dunglas/frankenphp.go_handle_request()
/go/src/app/frankenphp.go:474 +0x9b fp=0xc0008d1e48 sp=0xc0008d1d80 pc=0x765efb
_cgoexp_a4e4414eb6e0_go_handle_request(0x7f25b07f7d2f)
_cgo_gotypes.go:916 +0x14 fp=0xc0008d1e58 sp=0xc0008d1e48 pc=0x76b114
runtime.cgocallbackg1(0x76b100, 0x7f25b07f7d2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:420 +0x2a5 fp=0xc0008d1f18 sp=0xc0008d1e58 pc=0x409485
runtime.cgocallbackg(0x76b100, 0x7f25b07f7d2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:339 +0x136 fp=0xc0008d1f90 sp=0xc0008d1f18 pc=0x409136
runtime.cgocallbackg(0x76b100, 0x7f25b07f7d2f, 0x0)
goroutine 212 gp=0xc000562e00 m=nil [select, locked to thread]:
runtime.gopark(0xc0008cfe08?, 0x2?, 0x20?, 0x13?, 0xc0008cfdcc?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc0008cfc60 sp=0xc0008cfc40 pc=0x44198e
runtime.selectgo(0xc0008cfe08, 0xc0008cfdc8, 0x0?, 0x0, 0xc000562e00?, 0x1)
/usr/local/go/src/runtime/select.go:327 +0x725 fp=0xc0008cfd80 sp=0xc0008cfc60 pc=0x453725
github.com/dunglas/frankenphp.go_handle_request()
/go/src/app/frankenphp.go:474 +0x9b fp=0xc0008cfe48 sp=0xc0008cfd80 pc=0x765efb
_cgoexp_a4e4414eb6e0_go_handle_request(0x7f25fb7fdd2f)
_cgo_gotypes.go:916 +0x14 fp=0xc0008cfe58 sp=0xc0008cfe48 pc=0x76b114
runtime.cgocallbackg1(0x76b100, 0x7f25fb7fdd2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:420 +0x2a5 fp=0xc0008cff18 sp=0xc0008cfe58 pc=0x409485
runtime.cgocallbackg(0x76b100, 0x7f25fb7fdd2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:339 +0x136 fp=0xc0008cff90 sp=0xc0008cff18 pc=0x409136
runtime.cgocallbackg(0x76b100, 0x7f25fb7fdd2f, 0x0)
goroutine 213 gp=0xc000563500 m=nil [select, locked to thread]:
runtime.gopark(0xc000f95e08?, 0x2?, 0xc0?, 0xfb?, 0xc000f95dcc?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc000f95c60 sp=0xc000f95c40 pc=0x44198e
runtime.selectgo(0xc000f95e08, 0xc000f95dc8, 0x0?, 0x0, 0xc000563500?, 0x1)
/usr/local/go/src/runtime/select.go:327 +0x725 fp=0xc000f95d80 sp=0xc000f95c60 pc=0x453725
github.com/dunglas/frankenphp.go_handle_request()
/go/src/app/frankenphp.go:474 +0x9b fp=0xc000f95e48 sp=0xc000f95d80 pc=0x765efb
_cgoexp_a4e4414eb6e0_go_handle_request(0x7f25faffcd2f)
_cgo_gotypes.go:916 +0x14 fp=0xc000f95e58 sp=0xc000f95e48 pc=0x76b114
runtime.cgocallbackg1(0x76b100, 0x7f25faffcd2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:420 +0x2a5 fp=0xc000f95f18 sp=0xc000f95e58 pc=0x409485
runtime.cgocallbackg(0x76b100, 0x7f25faffcd2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:339 +0x136 fp=0xc000f95f90 sp=0xc000f95f18 pc=0x409136
runtime.cgocallbackg(0x76b100, 0x7f25faffcd2f, 0x0)
goroutine 214 gp=0xc000563c00 m=nil [select, locked to thread]:
runtime.gopark(0xc000dafe08?, 0x2?, 0x0?, 0xf2?, 0xc000dafdcc?)
/usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc000dafc60 sp=0xc000dafc40 pc=0x44198e
runtime.selectgo(0xc000dafe08, 0xc000dafdc8, 0x0?, 0x0, 0xc000563c00?, 0x1)
/usr/local/go/src/runtime/select.go:327 +0x725 fp=0xc000dafd80 sp=0xc000dafc60 pc=0x453725
github.com/dunglas/frankenphp.go_handle_request()
/go/src/app/frankenphp.go:474 +0x9b fp=0xc000dafe48 sp=0xc000dafd80 pc=0x765efb
_cgoexp_a4e4414eb6e0_go_handle_request(0x7f25fa7fbd2f)
_cgo_gotypes.go:916 +0x14 fp=0xc000dafe58 sp=0xc000dafe48 pc=0x76b114
runtime.cgocallbackg1(0x76b100, 0x7f25fa7fbd2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:420 +0x2a5 fp=0xc000daff18 sp=0xc000dafe58 pc=0x409485
runtime.cgocallbackg(0x76b100, 0x7f25fa7fbd2f, 0x0)
/usr/local/go/src/runtime/cgocall.go:339 +0x136 fp=0xc000daff90 sp=0xc000daff18 pc=0x409136
runtime.cgocallbackg(0x76b100, 0x7f25fa7fbd2f, 0x0)
goroutine 7104 gp=0xc000403dc0 m=12 mp=0xc000580008 [syscall]: runtime.cgocall(0x790d60, 0xc0002c7f78) /usr/local/go/src/runtime/cgocall.go:157 +0x4b fp=0xc0002c7f50 sp=0xc0002c7f18 pc=0x408d2b github.com/dunglas/go-fswatch._Cfunc_fsw_start_monitor(0x7f2514000b70) _cgo_gotypes.go:345 +0x47 fp=0xc0002c7f78 sp=0xc0002c7f50 pc=0x71eca7 github.com/dunglas/frankenphp.initWatcher.gowrap2.(*Session).Start.1(0xc0002c7fd0?) /go/pkg/mod/github.com/dunglas/[email protected]/fswatch.go:32 +0x3e fp=0xc0002c7fb8 sp=0xc0002c7f78 pc=0x760f7e github.com/dunglas/go-fswatch.(*Session).Start(...) /go/pkg/mod/github.com/dunglas/[email protected]/fswatch.go:32 github.com/dunglas/frankenphp.initWatcher.gowrap2() /go/src/app/watcher.go:36 +0x25 fp=0xc0002c7fe0 sp=0xc0002c7fb8 pc=0x760f05 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc0002c7fe8 sp=0xc0002c7fe0 pc=0x478ac1 created by github.com/dunglas/frankenphp.initWatcher in goroutine 7368 /go/src/app/watcher.go:36 +0x1d1
goroutine 7368 gp=0xc00042ca80 m=nil [semacquire]: runtime.gopark(0xc000277cf0?, 0xc000277d28?, 0x60?, 0x6?, 0xc000277d08?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc000277c98 sp=0xc000277c78 pc=0x44198e runtime.goparkunlock(...) /usr/local/go/src/runtime/proc.go:408 runtime.semacquire1(0xc000869108, 0x0, 0x1, 0x0, 0x12) /usr/local/go/src/runtime/sema.go:160 +0x225 fp=0xc000277d00 sp=0xc000277c98 pc=0x454765 sync.runtime_Semacquire(0xc0005abcf8?) /usr/local/go/src/runtime/sema.go:62 +0x25 fp=0xc000277d38 sp=0xc000277d00 pc=0x474bc5 sync.(*WaitGroup).Wait(0x8f56f0?) /usr/local/go/src/sync/waitgroup.go:116 +0x48 fp=0xc000277d60 sp=0xc000277d38 pc=0x4833e8 github.com/dunglas/frankenphp_test.runTest(0xc011766340, 0xc011769c00, 0x24?) /go/src/app/frankenphp_test.go:98 +0x6b2 fp=0xc000277ee8 sp=0xc000277d60 pc=0x77ca32 github.com/dunglas/frankenphp_test.TestWorkerShouldReloadOnMatchingPattern(0xc011766340) /go/src/app/watcher_test.go:21 +0xbf fp=0xc000277f70 sp=0xc000277ee8 pc=0x78bb1f testing.tRunner(0xc011766340, 0x8869c0) /usr/local/go/src/testing/testing.go:1689 +0xfb fp=0xc000277fc0 sp=0xc000277f70 pc=0x50a1fb testing.(*T).Run.gowrap1() /usr/local/go/src/testing/testing.go:1742 +0x25 fp=0xc000277fe0 sp=0xc000277fc0 pc=0x50b225 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc000277fe8 sp=0xc000277fe0 pc=0x478ac1 created by testing.(*T).Run in goroutine 1 /usr/local/go/src/testing/testing.go:1742 +0x390
goroutine 7369 gp=0xc000129dc0 m=nil [chan receive]: runtime.gopark(0x2?, 0x0?, 0x0?, 0x0?, 0xc00092e0a0?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc011b93b98 sp=0xc011b93b78 pc=0x44198e runtime.chanrecv(0xc01173fd40, 0x0, 0x1) /usr/local/go/src/runtime/chan.go:583 +0x3bf fp=0xc011b93c10 sp=0xc011b93b98 pc=0x40b3bf runtime.chanrecv1(0xc011b93c98?, 0xc011b93c70?) /usr/local/go/src/runtime/chan.go:442 +0x12 fp=0xc011b93c38 sp=0xc011b93c10 pc=0x40aff2 github.com/dunglas/frankenphp.ServeHTTP({0x0, 0x0}, 0xc0117750e0) /go/src/app/frankenphp.go:466 +0x20e fp=0xc011b93cf8 sp=0xc011b93c38 pc=0x765d2e github.com/dunglas/frankenphp.startWorkers.func1() /go/src/app/worker.go:87 +0x3e6 fp=0xc011b93fe0 sp=0xc011b93cf8 pc=0x768ee6 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc011b93fe8 sp=0xc011b93fe0 pc=0x478ac1 created by github.com/dunglas/frankenphp.startWorkers in goroutine 7368 /go/src/app/worker.go:65 +0x34e
goroutine 7105 gp=0xc0009be380 m=nil [runnable]: runtime.gopark(0x2?, 0xc0118de360?, 0x2d?, 0x0?, 0xc000306d20?) /usr/local/go/src/runtime/proc.go:402 +0xce fp=0xc000306cd0 sp=0xc000306cb0 pc=0x44198e runtime.chanrecv(0xc000a11380, 0x0, 0x1) /usr/local/go/src/runtime/chan.go:583 +0x3bf fp=0xc000306d48 sp=0xc000306cd0 pc=0x40b3bf runtime.chanrecv1(0xc000306dd0?, 0xc000306da8?) /usr/local/go/src/runtime/chan.go:442 +0x12 fp=0xc000306d70 sp=0xc000306d48 pc=0x40aff2 github.com/dunglas/frankenphp.ServeHTTP({0x8f68b0, 0xc011899380}, 0xc0118c5320) /go/src/app/frankenphp.go:466 +0x20e fp=0xc000306e30 sp=0xc000306d70 pc=0x765d2e github.com/dunglas/frankenphp_test.runTest.func1({0x8f68b0, 0xc011899380}, 0x86175e?) /go/src/app/frankenphp_test.go:79 +0xc8 fp=0xc000306eb0 sp=0xc000306e30 pc=0x77cca8 github.com/dunglas/frankenphp_test.fetchBody({0x84d909?, 0x7?}, {0x86175e?, 0x769700?}, 0xc0118b51c0) /go/src/app/watcher_test.go:60 +0xb6 fp=0xc000306f18 sp=0xc000306eb0 pc=0x78bfd6 github.com/dunglas/frankenphp_test.TestWorkerShouldReloadOnMatchingPattern.func1(0xc0118b51c0, 0x6666666666666666?, 0x6666666666666666?) /go/src/app/watcher_test.go:23 +0x45 fp=0xc000306f98 sp=0xc000306f18 pc=0x78bb85 github.com/dunglas/frankenphp_test.runTest.func2(0xc0115e5f20?) /go/src/app/frankenphp_test.go:93 +0x32 fp=0xc000306fc8 sp=0xc000306f98 pc=0x77cb52 github.com/dunglas/frankenphp_test.runTest.gowrap2() /go/src/app/frankenphp_test.go:95 +0x24 fp=0xc000306fe0 sp=0xc000306fc8 pc=0x77cae4 runtime.goexit({}) /usr/local/go/src/runtime/asm_amd64.s:1695 +0x1 fp=0xc000306fe8 sp=0xc000306fe0 pc=0x478ac1 created by github.com/dunglas/frankenphp_test.runTest in goroutine 7368 /go/src/app/frankenphp_test.go:92 +0x5b4
rax 0x4 rbx 0x7f2514000c74 rcx 0x1 rdx 0x7f2514000c74 rdi 0x10 rsi 0x7f2604000ed0 rbp 0x7f2604000d70 rsp 0x7f261bcdbbb0 r8 0x7 r9 0x0 r10 0x7f26667e3100 r11 0x7f2666817ef0 r12 0xe000061 r13 0x7f263c000ef4 r14 0x38000184 r15 0x2 rip 0x7f2666817f9b rflags 0x10202 cs 0x33 fs 0x0 gs 0x0 exit status 2
Additionally I can't modify the github workflows and fswatch would have to be installed everywhere there as well So I think it's better if you do it.
The dependency on fswatch definitely makes the whole building and testing process a lot more complicated compared to the pure go implementation of fsnotify. It does offer better compatibility though
I wonder if it's possible to bundle up the fswatch binary into go-fswatch directly so we could skip all these build steps.
And to adress your regex question, my original intention was to stay compatible with the wilcard syntax that chokidar also uses, like here in laravel octane: https://github.com/laravel/octane/blob/eef1549eb6d9a277c26cba2ad97a71625158e25a/config/octane.php#L186-L196
But I'm also fine with regex if there are other ways to abstract that away, people just tend to shoot themselves in the foot with regex 😅
Bundling the C lib in go-fswatch would be practical but will require huge CI work (similar to what we've done here for FrankenPHP) because we'll have to cross-compile the C lib.
Also, this is likely not what many users want as libfswatch is packaged by some distributions, including Debian (unfortunately, the current packaged version is too old to be used by go-fswatch, but it will likely be updated at some point). It's quite uncommon that Go modules bundle C libraries for these reasons.
IMHO it would be easier to handle that part directly in FrankenPHP, as we have most of the needed infrastructure.
Regarding regexp, I wouldn't bother with Chokidar compatibility. Chokidar will continue to work in Octane (so existing setups will not be broken). I agree that regexp are harder to master, but they are also more powerful.
Tests are finally looking more green 🎉 As mentioned I can't adjust the github actions, so we'll have to wait for you to do that once you return. The static build is currently generally failing, so that would have to be resolved first.
For the "tests" action, copying this should work: https://github.com/dunglas/go-fswatch/blob/main/.github/workflows/tests.yaml
The watcher now additionally supports the following configuration
{
frankenphp {
watch {
path /path/to/folder1
path /path/to/folder2
recursive true # watch subdirectories
follow_symlinks false # weather to follow symlinks
exclude \.log$ # regex, exclude all files ending with .log
include \system.log$ # regex, specifically include all files ending with system.log
case_sensitive false # use case sensitive regex
extended_regex false # use extended regex
monitor_type default # allowed: "default", "fsevents", "kqueue", "inotify", "windows", "poll", "fen"
delay 150 # delay of triggering file change events in ms
}
}
}
I was wondering is there an easy way to test the Caddy configuration without starting the whole frankenphp process?
I was wondering is there an easy way to test the Caddy configuration without starting the whole frankenphp process?
I believe you can run caddy to generate the config as a json file and then assert that the json file matches what you expected: caddy adapt --config Caddyfile --adapter caddyfile > caddy.json or something like that.
While reading a ticket on fswatch's bug tracker, I stumbled upon https://github.com/e-dant/watcher which looks even better:
- faster
- fanotify support on Linux (which is faster than inotify and has less limitations)
- maintained (fswtach looks unmaintained https://github.com/emcrisostomo/fswatch/issues/323, NeoVIM recently switched to another library because of this)
Integrating it with Go looks very easy: https://github.com/e-dant/watcher/issues/48#issuecomment-2336465809
I know it's bit late (sorry), but shouldn't we consider moving to this lib?
Yeah you are right, I also realized it wasn't properly maintained after seeing that the exclude filter was just broken on linux, which is a bummer since you built a whole go wrapper around it.
I'm open to switch to any filewatcher as long as it's easy to integrate and maintain.
What would the next step be then @dunglas ? Would we integrate the c lib directly here in frankenphp or in a separate repo or create a binding in their repo ?
The easiest option would of course be to just use the pure go solution, but it still lacks a ton of features
Would we integrate the c lib directly here in frankenphp or in a separate repo or create a binding in their repo ?
The C API is so simple (a single function) that both solutions could work. My current plan was to propose to add simple Go bindings directly in the main repository of the library, but maybe could we just integrate it in FrankenPHP in the meantime. It's basically a single cgo call.
The easiest option would of course be to just use the pure go solution, but it still lacks a ton of features
Yes, there is nothing ideal yet...
My current opinion is that we should make the used library purely internal, so we can switch easily to another one if necessary (ex: if a satisfaction pure Go solution emerges). To do so, we should make the config minimal, so we can easily switch the implementation. For now, maybe could we stick with fswatch, or switch to watcher (fanotify support is nice feature). We'll always be able to migrate to another solution later. WDYT?
Some downsides to e-dant/watcher that might affect you here
-
It only supports recursive watches. We do this because the performance impact is almost nothing (we test to be sure over many millions of events) and we've never had a feature request to change that. When I'm only interested in a single directory, I filter for it manually (either on the command-line or in the callback).
-
It does not debounce events out of the box. Some other repos do this, some do not. Some have it as an option or alternative library. Generally speaking, you want to consider debouncing at least the responding logic on events that can be unbounded in their frequency. This is very use-case specific.
-
It is a library focused on correctness, performance and simplicity. Sounds nice, ok, but it means that there are no fancy features out of the box. No path pattern matching (like chokidar), no daemon service (like watchman), no debouncing logic (discussed above), no non-fs-related stuff (qt). Watcher is among the more performant, well-tested and correct. It is not the most feature-rich.
Good luck whatever you choose!
If we are going the cgo route, I would definitely prefer e-dant/watcher because of fanotify and it generally feels more up-to-date.
A custom de-bounce was already necessary for fswatch and a simple pattern matching was inplemented for fsnotify before, so that shouldn't be a problem.
I've never used Cgo, but I can take a shot at it (still practicing my go skills 😉).
The only thing that worries me are the static builds since I have no idea how to make them work with these external libraries.
The only thing that worries me are the static builds since I have no idea how to make them work with these external libraries.
Checkout this C shared (or static) library for watcher: https://github.com/e-dant/watcher/tree/next/watcher-c
Basic usage here: https://github.com/e-dant/watcher/blob/next/watcher-c/src/test-watcher-c.c#L92-L95
If needed you can cross-compile it here: https://github.com/e-dant/watcher/blob/next/watcher-c/cross-compile.sh (for unix-like platforms, windows compilation should work but I don't have a toolchain in there for it)
Example build rules: https://github.com/e-dant/watcher/blob/next/watcher-c/meson.build#L26-L34 these are meson, but it can be whatever build system you want/need/prefer of course
I can handle the static part if you want @AlliBalliBaba, it's a bit tricky because this needs to be integrated into the static-php-cli process. Let me know if you need help with the cgo part, but it should be "straightforward" (as cgo can be).
e-dant/watcher is now built in in the bookworm images (still have to do alpine + cleanup). It works great 👍 , fanotify allows me to watch a big vendor folder (12.000 + files) without issues.
To keep it simple, now only the one-liners are allowed in the Caddy config, aka: /path/to/folder/**/*.php
Not sure if I did the cgo integration correctly, it's a bit of a type juggle. But I imagine we would switch to the go-wrapper if @dunglas decides to make that in the e-dant/watcher repo.
I'm installing the watcher via git and meson, which creates a libwatcher-c-0.11.0.so. Not sure if installing via meson is the best option here.
What still needs to happen before this PR is finished:
- [x] install
edant/watcherso it works in arm - [x] this if we decide to stick with the meson installer
- [x] install
edant/watcherin the test github actions - [x] install
edant/watcherso it works in the static binary - [x] lint the c files correctly (not sure how yet)
- [x] ~~find a way to clear opcache after restarting workers~~ this seems to not be necessary after all
- [x] finalize the docs once everything is finished
Would it be useful to you if I added CI in watcher for arm (64/a53/72, and 32/v7), x86/64, glibc and musl, for kernels > v5 or v6 ish on Linux?
IOW, to make available the shared libraries for the platforms you need as downloads
While it would be nice to have a download, I don't think it's necessary since we're running the pipelines here for all the supported environments anyways.
While it would be nice to have a download, I don't think it's necessary since we're running the pipelines here for all the supported environments anyways.
I added a job here: https://github.com/e-dant/watcher/actions/runs/10866030391
It should include the c libs, headers, and some of the example cli utilities. And shasums of the binaries, filed.
Triplets currently built:
- x86_64-unknown-linux-musl
- x86_64-unknown-linux-gnu
- armv7-unknown-linux-musleabihf
- armv7-unknown-linux-gnueabihf
- aarch64-unknown-linux-musl
- aarch64-unknown-linux-gnu
- aarch64-apple-darwin
It was probably time we added CI for those artifacts, whether or not you choose to use them.
Cheers
@dunglas is there a trick to make the static build work with libraries that depend on libstdc++? (like edant/watcher)
I've tried as a shared and a static library but it always ends up complaining about not finding libgcc_s, which is weird since gcc is installed in the static-builder Dockerfile. Does the library have to be linked or complied in a very specific way?
Does the library have to be linked or complied in a very specific way?
I don't know if there's any magic above the C/++ code that's needed, but at least for the watcher shared lib here in isolation, there shouldn't be anything special. The library should only link to some barebones system libraries, like these for example on Linux x86/64:
$ ldd out/x86_64-unknown-linux-gnu/libwatcher-c.so
linux-vdso.so.1 (0x00007ffd0b37f000)
libstdc++.so.6 => /usr/local/lib64/libstdc++.so.6 (0x00007f0d47a00000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0d4781f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0d47db3000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f0d47ca3000)
libgcc_s.so.1 => /usr/local/lib64/libgcc_s.so.1 (0x00007f0d47c82000)
These flags shouldn't be added. It's likely a bug or a limitation in php-config itself or in some extensions. This patch should work as a workaround: https://github.com/dunglas/frankenphp/pull/1026
msan seems to be complaining about an uninitialized value in the watcher itself with infotiy
I'm not sure if this is legit or by design since I'm not very familiar with C++ @e-dant