I ran into a confusing scenario where I think Postgres.app should have reported "Port in use" and failed to start, but instead managed to bind and steal traffic from a process that was already listening on that port.
I have a Docker container running PostGIS and exposing container port 5432 on host port 5432. I was able to open a psql shell on port 5432, but was confused because the database didn't have the right data. Eventually I figured out that Postgres.app was also listening on port 5432:
$ sudo lsof -i :5432
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
com.docke 1029 wchargin 128u IPv6 0x97e222976b6cf6c5 0t0 TCP *:postgresql (LISTEN)
postgres 45709 wchargin 7u IPv6 0x91b1855dc1c99cac 0t0 TCP localhost:postgresql (LISTEN)
postgres 45709 wchargin 8u IPv4 0xa012493f18604ea9 0t0 TCP localhost:postgresql (LISTEN)
$ ps -p 45709 -o comm
COMM
/Applications/Postgres.app/Contents/Versions/16/bin/postgres
I searched the source for SO_REUSEPORT / SO_REUSEADDR and found the comment leading to #676. I'm glad that that issue is resolved, but it seems like this issue is an unfortunate consequence of the fix.
I do think that it may be somewhat confusing to use this socket option, since it subverts the application that if an application is listening on a port then it will be able to receive packets sent to that port. Notably, this confusion only occurs because my Docker container is listening on all interfaces. If I expose 127.0.0.1:5432:5432 instead of just 5432:5432, then Postgres.app properly reports "Port in use" or the Docker container fails with "Ports are not available". So it feels a bit clumsy and unpredictable that Postgres.app behaves this way.
Might there be a different way of solving the original issue that doesn't cause this side-effect?
Steps to reproduce
- Make sure that Postgres.app is stopped.
- Run
docker run --rm -e POSTGRES_PASSWORD=password -p 5432:5432 -it postgres, and leave that running in its own terminal.
- Run
psql -h localhost -p 5432 -U postgres, and execute (say) CREATE TABLE tab(), SELECT count(1) FROM tab.
- Start Postgres.app. Note that it moves to the "Running" state without any error.
- Run
psql -h localhost -p 5432 -U postgres again. Note that SELECT count(1) FROM tab now fails: no such relation.
If you have the psql shells from (3) and (5) open at the same time, you can note that their \conninfos report identical results:
You are connected to database "postgres" as user "postgres" on host "localhost" (address "::1") at port "5432".
…yet they are actually talking to different clusters!
(Then you can Ctrl-C in the terminal from step 2, which will destroy the container.)
I ran into a confusing scenario where I think Postgres.app should have reported "Port in use" and failed to start, but instead managed to bind and steal traffic from a process that was already listening on that port.
I have a Docker container running PostGIS and exposing container port 5432 on host port 5432. I was able to open a
psqlshell on port 5432, but was confused because the database didn't have the right data. Eventually I figured out that Postgres.app was also listening on port 5432:I searched the source for
SO_REUSEPORT/SO_REUSEADDRand found the comment leading to #676. I'm glad that that issue is resolved, but it seems like this issue is an unfortunate consequence of the fix.I do think that it may be somewhat confusing to use this socket option, since it subverts the application that if an application is listening on a port then it will be able to receive packets sent to that port. Notably, this confusion only occurs because my Docker container is listening on all interfaces. If I expose
127.0.0.1:5432:5432instead of just5432:5432, then Postgres.app properly reports "Port in use" or the Docker container fails with "Ports are not available". So it feels a bit clumsy and unpredictable that Postgres.app behaves this way.Might there be a different way of solving the original issue that doesn't cause this side-effect?
Steps to reproduce
docker run --rm -e POSTGRES_PASSWORD=password -p 5432:5432 -it postgres, and leave that running in its own terminal.psql -h localhost -p 5432 -U postgres, and execute (say)CREATE TABLE tab(),SELECT count(1) FROM tab.psql -h localhost -p 5432 -U postgresagain. Note thatSELECT count(1) FROM tabnow fails: no such relation.If you have the
psqlshells from (3) and (5) open at the same time, you can note that their\conninfos report identical results:…yet they are actually talking to different clusters!
(Then you can Ctrl-C in the terminal from step 2, which will destroy the container.)