Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug with parallel #791

Closed
davidnurdin opened this issue May 15, 2024 · 4 comments · Fixed by #883
Closed

Bug with parallel #791

davidnurdin opened this issue May 15, 2024 · 4 comments · Fixed by #883
Labels
bug Something isn't working

Comments

@davidnurdin
Copy link

What happened?

Seem on version 1.2.5 , parallel is crashing (with server mode)

sudo ./frankenphp-linux-x86_64 php-server index.php

❯ cat index.php 
<?php
$runtime = new \parallel\Runtime();

$future = $runtime->run(function(){
    for ($i = 0; $i < 500; $i++)
        echo "*";

    return "easy";
});

for ($i = 0; $i < 500; $i++) {
    echo ".";
}

printf("\nUsing \\parallel\\Runtime is %s\n", $future->value());

===> Loading N times http://localhost

Working some times then crash 👍

`

2024/05/15 14:30:16.513	WARN	admin	admin endpoint disabled
2024/05/15 14:30:16.513	WARN	http.auto_https	server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server	{"server_name": "php", "http_port": 80}
2024/05/15 14:30:16.513	INFO	tls.cache.maintenance	started background certificate maintenance	{"cache": "0xc000149e00"}
2024/05/15 14:30:16.514	INFO	http.log	server running	{"name": "php", "protocols": ["h1", "h2", "h3"]}
2024/05/15 14:30:16.514	INFO	FrankenPHP started 🐘	{"php_version": "8.3.7"}
2024/05/15 14:30:16.514	INFO	Caddy serving PHP app on :80
2024/05/15 14:30:16.519	WARN	tls	storage cleaning happened too recently; skipping for now	{"storage": "FileStorage:/root/.local/share/caddy", "instance": "18f83e8b-04c2-44af-a8ee-3a629c0cddcb", "try_again": "2024/05/16 14:30:16.519", "try_again_in": 86399.999999624}
2024/05/15 14:30:16.519	INFO	tls	finished cleaning storage units
fatal error: concurrent map read and map write

goroutine 106 [running, locked to thread]:
net/textproto.MIMEHeader.Get(0xc00013dec0, {0x7f5e63b56432?, 0xc0001f2db0?})
	/usr/local/go/src/net/textproto/header.go:34 +0x3f
net/http.Header.Get(...)
	/usr/local/go/src/net/http/header.go:50
github.com/caddyserver/caddy/v2/modules/caddyhttp/encode.(*responseWriter).Write(0xc00078b680, {0x7f5e110007c8, 0x1, 0x1})
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/encode/encode.go:246 +0x85
github.com/dunglas/frankenphp.go_ub_write(0xc0000c6000?, 0x7f5e110007c8, 0x1)
	/go/src/app/frankenphp.go:531 +0x13f

goroutine 1 [select (no cases)]:
github.com/dunglas/frankenphp/caddy.cmdPHPServer({0x0?})
	/go/src/app/caddy/php-server.go:329 +0x27d0
github.com/dunglas/frankenphp/caddy.init.2.func1.WrapCommandFuncForCobra.1(0xc000427208, {0x7f5e63b3d48d?, 0x4?, 0x7f5e63b3d295?})
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/cmd/cobra.go:137 +0x2f
github.com/spf13/cobra.(*Command).execute(0xc000427208, {0xc0004868d0, 0x1, 0x1})
	/go/pkg/mod/github.com/spf13/cobra@v1.8.0/command.go:983 +0xaca
github.com/spf13/cobra.(*Command).ExecuteC(0x7f5e68291080)
	/go/pkg/mod/github.com/spf13/cobra@v1.8.0/command.go:1115 +0x3ff
github.com/spf13/cobra.(*Command).Execute(...)
	/go/pkg/mod/github.com/spf13/cobra@v1.8.0/command.go:1039
github.com/caddyserver/caddy/v2/cmd.Main()
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/cmd/main.go:66 +0x5b
main.main()
	/go/src/app/caddy/frankenphp/main.go:24 +0x18d

goroutine 17 [select, locked to thread]:
github.com/dunglas/frankenphp.go_fetch_request()
	/go/src/app/frankenphp.go:473 +0x75

goroutine 9 [select]:
github.com/golang/glog.(*fileSink).flushDaemon(0x7f5e6837b538)
	/go/pkg/mod/github.com/golang/glog@v1.2.1/glog_file.go:351 +0xb9
created by github.com/golang/glog.init.1 in goroutine 1
	/go/pkg/mod/github.com/golang/glog@v1.2.1/glog_file.go:166 +0x126

goroutine 35 [chan receive]:
github.com/dunglas/frankenphp.ServeHTTP({0x7f5e6750a7d0, 0xc00078b680}, 0xc0006e5200)
	/go/src/app/frankenphp.go:465 +0x20e
github.com/dunglas/frankenphp/caddy.FrankenPHPModule.ServeHTTP({{0x7f5e63b5afd2, 0x10}, {0xc000137a50, 0x1, 0x1}, 0xc00033ed40, 0x0, 0xc000505500}, {0x7f5e6750a7d0, 0xc00078b680}, ...)
	/go/src/app/caddy/caddy.go:275 +0x4ac
github.com/caddyserver/caddy/v2/modules/caddyhttp.wrapMiddleware.func1.1({0x7f5e6750a7d0?, 0xc00078b680?}, 0xc000317540?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/routes.go:331 +0x3a
github.com/caddyserver/caddy/v2/modules/caddyhttp.HandlerFunc.ServeHTTP(0x7f5e674fc800?, {0x7f5e6750a7d0?, 0xc00078b680?}, 0xc0006e4ea0?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/caddyhttp.go:58 +0x29
github.com/caddyserver/caddy/v2/modules/caddyhttp.RouteList.Compile.wrapRoute.func1.1({0x7f5e6750a7d0, 0xc00078b680}, 0xc0006e4ea0)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/routes.go:300 +0x325
github.com/caddyserver/caddy/v2/modules/caddyhttp.HandlerFunc.ServeHTTP(0x0?, {0x7f5e6750a7d0?, 0xc00078b680?}, 0xc000149400?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/caddyhttp.go:58 +0x29
github.com/caddyserver/caddy/v2/modules/caddyhttp/rewrite.Rewrite.ServeHTTP({{0x0, 0x0}, {0xc00079cb80, 0x1d}, {0x0, 0x0}, {0x0, 0x0}, {0x0, 0x0, ...}, ...}, ...)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/rewrite/rewrite.go:137 +0x3f3
github.com/caddyserver/caddy/v2/modules/caddyhttp.wrapMiddleware.func1.1({0x7f5e6750a7d0?, 0xc00078b680?}, 0xc000505300?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/routes.go:331 +0x3a
github.com/caddyserver/caddy/v2/modules/caddyhttp.HandlerFunc.ServeHTTP(0x7f5e674fc800?, {0x7f5e6750a7d0?, 0xc00078b680?}, 0xc0006e4ea0?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/caddyhttp.go:58 +0x29
github.com/caddyserver/caddy/v2/modules/caddyhttp.RouteList.Compile.wrapRoute.func1.1({0x7f5e6750a7d0, 0xc00078b680}, 0xc0006e4ea0)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/routes.go:300 +0x325
github.com/caddyserver/caddy/v2/modules/caddyhttp.HandlerFunc.ServeHTTP(0x7f5e6750ec60?, {0x7f5e6750a7d0?, 0xc00078b680?}, 0xe?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/caddyhttp.go:58 +0x29
github.com/caddyserver/caddy/v2/modules/caddyhttp.RouteList.Compile.wrapRoute.func1.1({0x7f5e6750a7d0, 0xc00078b680}, 0xc0006e4ea0)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/routes.go:268 +0x244
github.com/caddyserver/caddy/v2/modules/caddyhttp.HandlerFunc.ServeHTTP(0xc000801480?, {0x7f5e6750a7d0?, 0xc00078b680?}, 0x4?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/caddyhttp.go:58 +0x29
github.com/caddyserver/caddy/v2/modules/caddyhttp/encode.(*Encode).ServeHTTP(0xc000317400, {0x7f5e6750a0e0, 0xc00063f340}, 0xc0006e4ea0, {0x7f5e674fc800, 0xc00025f240})
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/encode/encode.go:138 +0x252
github.com/caddyserver/caddy/v2/modules/caddyhttp.wrapMiddleware.func1.1({0x7f5e6750a0e0?, 0xc00063f340?}, 0xc000317400?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/routes.go:331 +0x3a
github.com/caddyserver/caddy/v2/modules/caddyhttp.HandlerFunc.ServeHTTP(0x7f5e674fc800?, {0x7f5e6750a0e0?, 0xc00063f340?}, 0xc0006e4ea0?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/caddyhttp.go:58 +0x29
github.com/caddyserver/caddy/v2/modules/caddyhttp.RouteList.Compile.wrapRoute.func1.1({0x7f5e6750a0e0, 0xc00063f340}, 0xc0006e4ea0)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/routes.go:300 +0x325
github.com/caddyserver/caddy/v2/modules/caddyhttp.HandlerFunc.ServeHTTP(0xc0001bca08?, {0x7f5e6750a0e0?, 0xc00063f340?}, 0x7f5e674fc800?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/caddyhttp.go:58 +0x29
github.com/caddyserver/caddy/v2/modules/caddyhttp.(*Subroute).ServeHTTP(0xc0006b6f00, {0x7f5e6750a0e0, 0xc00063f340}, 0xc0006e4ea0, {0x7f5e674fc800, 0x7f5e674f0378})
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/subroute.go:74 +0x67
github.com/caddyserver/caddy/v2/modules/caddyhttp.wrapMiddleware.func1.1({0x7f5e6750a0e0?, 0xc00063f340?}, 0xc0006b6f00?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/routes.go:331 +0x3a
github.com/caddyserver/caddy/v2/modules/caddyhttp.HandlerFunc.ServeHTTP(0x7f5e674fc800?, {0x7f5e6750a0e0?, 0xc00063f340?}, 0xc0006e4ea0?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/caddyhttp.go:58 +0x29
github.com/caddyserver/caddy/v2/modules/caddyhttp.RouteList.Compile.wrapRoute.func1.1({0x7f5e6750a0e0, 0xc00063f340}, 0xc0006e4ea0)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/routes.go:300 +0x325
github.com/caddyserver/caddy/v2/modules/caddyhttp.HandlerFunc.ServeHTTP(0x7f5e6743f260?, {0x7f5e6750a0e0?, 0xc00063f340?}, 0xc0008013c0?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/caddyhttp.go:58 +0x29
github.com/caddyserver/caddy/v2/modules/caddyhttp.(*Server).enforcementHandler(0x10?, {0x7f5e6750a0e0?, 0xc00063f340?}, 0x0?, {0x7f5e674fc800?, 0xc0006b70e0?})
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/server.go:429 +0x24b
github.com/caddyserver/caddy/v2/modules/caddyhttp.(*App).Provision.(*Server).wrapPrimaryRoute.func1({0x7f5e6750a0e0?, 0xc00063f340?}, 0x7f5e61011b6f?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/server.go:405 +0x35
github.com/caddyserver/caddy/v2/modules/caddyhttp.HandlerFunc.ServeHTTP(0xc000420380?, {0x7f5e6750a0e0?, 0xc00063f340?}, 0xc0006e4ea0?)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/caddyhttp.go:58 +0x29
github.com/caddyserver/caddy/v2/modules/caddyhttp.(*Server).ServeHTTP(0xc000236848, {0x7f5e6750a0e0, 0xc00063f340}, 0xc0006e4b40)
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/server.go:341 +0xc47
net/http.serverHandler.ServeHTTP({0xc0005fc1b0?}, {0x7f5e6750a0e0?, 0xc00063f340?}, 0x6?)
	/usr/local/go/src/net/http/server.go:3137 +0x8e
net/http.(*conn).serve(0xc00062e000, {0x7f5e6750ec60, 0xc0005fc120})
	/usr/local/go/src/net/http/server.go:2039 +0x5e8
created by net/http.(*Server).Serve in goroutine 30
	/usr/local/go/src/net/http/server.go:3285 +0x4b4

goroutine 10 [sync.Cond.Wait]:
sync.runtime_notifyListWait(0xc000000318, 0x0)
	/usr/local/go/src/runtime/sema.go:569 +0x15a
sync.(*Cond).Wait(0xc00036ddc0?)
	/usr/local/go/src/sync/cond.go:70 +0x85
github.com/maypok86/otter/internal/queue.(*Growable[...]).Pop(0x7f5e67525960)
	/go/pkg/mod/github.com/maypok86/otter@v1.2.1/internal/queue/growable.go:71 +0x74
github.com/maypok86/otter/internal/core.(*Cache[...]).process(0x7f5e67542dc0)
	/go/pkg/mod/github.com/maypok86/otter@v1.2.1/internal/core/cache.go:386 +0xe8
created by github.com/maypok86/otter/internal/core.NewCache[...] in goroutine 1
	/go/pkg/mod/github.com/maypok86/otter@v1.2.1/internal/core/cache.go:167 +0x6b3

goroutine 14 [select]:
github.com/caddyserver/certmagic.(*RingBufferRateLimiter).permit(0xc00078ac30)
	/go/pkg/mod/github.com/caddyserver/certmagic@v0.20.0/ratelimiter.go:217 +0x86
github.com/caddyserver/certmagic.(*RingBufferRateLimiter).loop(0xc00078ac30)
	/go/pkg/mod/github.com/caddyserver/certmagic@v0.20.0/ratelimiter.go:89 +0x8b
created by github.com/caddyserver/certmagic.NewRateLimiter in goroutine 1
	/go/pkg/mod/github.com/caddyserver/certmagic@v0.20.0/ratelimiter.go:45 +0x13c

goroutine 26 [chan receive]:
github.com/caddyserver/caddy/v2.trapSignalsCrossPlatform.func1()
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/sigtrap.go:43 +0xe5
created by github.com/caddyserver/caddy/v2.trapSignalsCrossPlatform in goroutine 1
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/sigtrap.go:38 +0x1a

goroutine 27 [chan receive]:
github.com/caddyserver/caddy/v2.trapSignalsPosix.func1()
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/sigtrap_posix.go:35 +0x105
created by github.com/caddyserver/caddy/v2.trapSignalsPosix in goroutine 1
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/sigtrap_posix.go:31 +0x1a

goroutine 67 [syscall]:
os/signal.signal_recv()
	/usr/local/go/src/runtime/sigqueue.go:152 +0x29
os/signal.loop()
	/usr/local/go/src/os/signal/signal_unix.go:23 +0x13
created by os/signal.Notify.func1.1 in goroutine 26
	/usr/local/go/src/os/signal/signal.go:151 +0x1f

goroutine 28 [select]:
github.com/caddyserver/certmagic.(*Cache).maintainAssets(0xc000149e00, 0x0)
	/go/pkg/mod/github.com/caddyserver/certmagic@v0.20.0/maintain.go:69 +0x31f
created by github.com/caddyserver/certmagic.NewCache in goroutine 1
	/go/pkg/mod/github.com/caddyserver/certmagic@v0.20.0/cache.go:127 +0x1f6

goroutine 29 [select]:
github.com/caddyserver/caddy/v2/modules/caddytls.(*TLS).keepStorageClean.func1()
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddytls/tls.go:540 +0x93
created by github.com/caddyserver/caddy/v2/modules/caddytls.(*TLS).keepStorageClean in goroutine 1
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddytls/tls.go:532 +0xe5

goroutine 30 [IO wait]:
internal/poll.runtime_pollWait(0x7f5e1c6806d0, 0x72)
	/usr/local/go/src/runtime/netpoll.go:345 +0x85
internal/poll.(*pollDesc).wait(0x3?, 0x7f5e60f7f285?, 0x0)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:84 +0x27
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).Accept(0xc000505880)
	/usr/local/go/src/internal/poll/fd_unix.go:611 +0x2ac
net.(*netFD).accept(0xc000505880)
	/usr/local/go/src/net/fd_unix.go:172 +0x29
net.(*TCPListener).accept(0xc0006b7160)
	/usr/local/go/src/net/tcpsock_posix.go:159 +0x1e
net.(*TCPListener).Accept(0xc0006b7160)
	/usr/local/go/src/net/tcpsock.go:327 +0x30
net/http.(*Server).Serve(0xc0007a3770, {0x7f5e1c064100, 0xc0006b7180})
	/usr/local/go/src/net/http/server.go:3255 +0x33e
created by github.com/caddyserver/caddy/v2/modules/caddyhttp.(*App).Start in goroutine 1
	/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.7.6/modules/caddyhttp/app.go:509 +0x1b95

goroutine 82 [syscall, locked to thread]:
runtime.goexit({})
	/usr/local/go/src/runtime/asm_amd64.s:1695 +0x1

goroutine 83 [syscall, locked to thread]:
runtime.goexit({})
	/usr/local/go/src/runtime/asm_amd64.s:1695 +0x1

goroutine 84 [syscall, locked to thread]:
runtime.goexit({})
	/usr/local/go/src/runtime/asm_amd64.s:1695 +0x1

goroutine 101 [syscall, locked to thread]:
runtime.goexit({})
	/usr/local/go/src/runtime/asm_amd64.s:1695 +0x1

goroutine 102 [syscall, locked to thread]:
runtime.goexit({})
	/usr/local/go/src/runtime/asm_amd64.s:1695 +0x1

goroutine 103 [syscall, locked to thread]:
github.com/dunglas/frankenphp._Cfunc_frankenphp_execute_script(0x7f5e10a65710)
	_cgo_gotypes.go:1089 +0x4b
github.com/dunglas/frankenphp.go_execute_script(0x4001?)
	/go/src/app/frankenphp.go:511 +0x133

goroutine 104 [syscall, locked to thread]:
runtime.goexit({})
	/usr/local/go/src/runtime/asm_amd64.s:1695 +0x1

goroutine 105 [syscall, locked to thread]:
runtime.goexit({})
	/usr/local/go/src/runtime/asm_amd64.s:1695 +0x1

goroutine 113 [IO wait]:
internal/poll.runtime_pollWait(0x7f5e1c6805d8, 0x72)
	/usr/local/go/src/runtime/netpoll.go:345 +0x85
internal/poll.(*pollDesc).wait(0xc00078c080?, 0xc0005fc1c1?, 0x0)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:84 +0x27
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).Read(0xc00078c080, {0xc0005fc1c1, 0x1, 0x1})
	/usr/local/go/src/internal/poll/fd_unix.go:164 +0x27a
net.(*netFD).Read(0xc00078c080, {0xc0005fc1c1?, 0x0?, 0x0?})
	/usr/local/go/src/net/fd_posix.go:55 +0x25
net.(*conn).Read(0xc000380010, {0xc0005fc1c1?, 0x0?, 0x0?})
	/usr/local/go/src/net/net.go:179 +0x45
net/http.(*connReader).backgroundRead(0xc0005fc1b0)
	/usr/local/go/src/net/http/server.go:681 +0x37
created by net/http.(*connReader).startBackgroundRead in goroutine 35
	/usr/local/go/src/net/http/server.go:677 +0xba

~/poc/franken_parallel via 🐘 v8.2.18 took 7s 



`

Build Type

Docker (Debian Bookworm)

Worker Mode

Yes

Operating System

GNU/Linux

CPU Architecture

x86_64

PHP configuration

latest version 1.2.5 franken

Relevant log output

No response

@davidnurdin davidnurdin added the bug Something isn't working label May 15, 2024
@withinboredom
Copy link
Collaborator

Parallel extension probably isn't compatible with go stacks/memory, if I had to guess (possibly collisions with channels and other shenanigans, plus maintaining threads).

It's probably better to break out the Parallel code into a separate, regular php file.

I have been doing that for quite some time. I should probably open source my Parallel shims...

@dunglas
Copy link
Owner

dunglas commented Jun 24, 2024

The problem has been reported upstream and parallel has been unbundled from FrankenPHP. krakjoe/parallel#308

@realFlowControl
Copy link

Hey @davidnurdin 👋

the error fatal error: concurrent map read and map write looks like a race condition to me. I am not 100% sure and might be wrong but I can fix the problem with a simple

echo "foo";
flush();

at the beginning of the file.

What might be happing is the following: As soon as output is started, PHP will start creating the HTTP-Response. In case you are using user land threads (as the example code above would), you end up having two threads that do write to the same buffers/socket. I assume that both threads do echo "at the same time" and trigger the creating and sending the HTTP-Response to the client which causes this.

ext-parallel overwrites the SAPI's ub_write with a version that uses a mutex to make sure only one thread can echo at a time, but it seems there is more going on.

I'll have a look if I can see something and get back to you

@realFlowControl
Copy link

Hey @dunglas,

can you help me running FrankenPHP with go -race?
I am not an expert in Go, but this looks to me like goroutine 106 and 35 both accessing the same "map" (which I assume is the responseWriter or the FrankenPHPContext or something related to it). To me it looks like the following could happen here:

Besides goroutines 106 and 35 all seem to be idling, while 106 and 35 seem both to access the responseWriter. I do assume that 106 is the thread echoing out the .-char (the main thread), while 35 is the one echoing out the *-char. I'd further assume that while 35 is shutting down and writing it's output, 106 is still calling echo and writing to the same responseWriter causing the fatal error: concurrent map read and map write.

This is all assumptions, but this is as far as I could understand things happening.

But it boils down to the main problem being the concurrency with two (or more) threads that share the same underlying structures and streams in the SAPI without synchronisation.

I assume we'd need to guard access to whatever "concurrent map read and map write" is referring to with a mutex. What do you think @dunglas?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants