jackc / jackc/puddle

Application Hangs on `defer p.destructWG.Wait()` in Docker Environment

Open
#37 6 comments 1 reaction 0 assignees View on GitHub
Dominant language
Go
Stars
419
Forks
37
PR merge metrics
No merged PRs in 30d

Description

**Description**:
As described in issue #25, my application hangs on the statement `defer p.destructWG.Wait()`. Any deferred statement or code that should execute after `defer pool.Close()` does not run. This issue occurs when running the application in a Docker container (`FROM golang:1.22-alpine`) on a Windows host machine through Docker Desktop. I have not tested this in other environments.

**Steps to Reproduce**:
1. Run the application in a Docker container with the base image `golang:1.22-alpine`.
2. Execute the provided code snippet.
3. Observe that the application hangs on `defer p.destructWG.Wait()`.

**Expected Behavior**:
Deferred statements, including those after `defer pool.Close()`, should execute as expected.

**Actual Behavior**:
Deferred statements after `defer pool.Close()` do not execute, causing the application to hang.

**Environment**:
- Docker base image: `golang:1.22-alpine`
- Host OS: Windows (via Docker Desktop)

**Additional Context**:
This issue occurs in the context where an actual connection has not been made through the pool. Below is the simplified code used in my application:

```go
package main

import (
"context"
"errors"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
"os"
)

func main() {
err := run(context.Background())
if err != nil {
os.Exit(1)
}
}

func run(ctx context.Context) error {
// Create the pool in a run func which is called by main func

poolConfig, err := pgxpool.ParseConfig(/* applicationConfig.Dsn */)
if err != nil {
return err
}
poolConfig.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error {
// Here I register some custom types
return nil
}

pool, err := pgxpool.NewWithConfig(ctx, poolConfig)
if err != nil {
return err
}
defer pool.Close()

// More code where an error is returned from run to main func, like so:
err = aCallWhichFails()
if err != nil {
return err
}

return nil
}

func aCallWhichFails() error {
return errors.New("test")
}
```
Feel free to adjust any part of this as needed!

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the provided run function in the golang:1.22-alpine Docker environment, starting at defer pool.Close() and the reported defer p.destructWG.Wait() path. Compare behavior when no connection is made and when aCallWhichFails returns; done means pool.Close returns and deferred statements after it execute without hanging.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, go
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.