-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
Bug Description
watchMaster() in prefork.go kills child processes when os.Getppid() == 1, assuming the parent died and init adopted them. However, in Docker containers the application commonly is PID 1, so children immediately see their parent PID as 1 and call os.Exit(1) after the first 500ms tick.
https://github.com/gofiber/fiber/blob/main/prefork.go#L170-L174
for range time.NewTicker(watchInterval).C {
if os.Getppid() == 1 {
os.Exit(1)
}
}How to Reproduce
FROM golang:1.24-alpine AS builder
WORKDIR /src
COPY . .
RUN go build -o /app .
FROM alpine:3.21
COPY --from=builder /app /app
ENTRYPOINT ["/app"]package main
import (
"log"
"github.com/gofiber/fiber/v3"
)
func main() {
app := fiber.New()
app.Get("/", func(c fiber.Ctx) error {
return c.SendString("OK")
})
log.Fatal(app.Listen(":8000", fiber.ListenConfig{
EnablePrefork: true,
}))
}docker build -t test . && docker run --rm -p 8000:8000 test
Children spawn, then all exit with exit status 1 after ~500ms.
Expected Behavior
Prefork should work in Docker containers without requiring an external init process.
Workaround
Use tini as PID 1 so the app doesn't run as PID 1:
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/app"]Suggested Fix
Instead of checking os.Getppid() == 1, store the actual parent PID at startup and compare against that:
func watchMaster() {
ppid := os.Getppid()
for range time.NewTicker(watchInterval).C {
if os.Getppid() != ppid {
os.Exit(1)
}
}
}This correctly detects parent death (PID changes when reparented to init) regardless of the original parent's PID.
Fiber Version
v3.1.0
Code Snippet (optional)
See above.
Checklist:
- I agree to follow Fiber's Code of Conduct.
- I have searched for existing issues that describe my problem before opening this one.
- I understand that an issue that doesn't follow these guidelines may be closed without explanation.
Metadata
Metadata
Assignees
Type
Projects
Status