Skip to content

Commit 155ff1d

Browse files
committed
fix: Admin server dies silently
This is a workaround for Warp crashing with "thread blocked indefinitely in an STM transaction" when receiving eMFILE from accept. The fix is to provide Warp with a custom accept function that handles eMFILE by logging it and keeping accepting connections.
1 parent 69d21a8 commit 155ff1d

1 file changed

Lines changed: 19 additions & 4 deletions

File tree

src/PostgREST/Admin.hs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ module PostgREST.Admin
22
( runAdmin
33
) where
44

5+
import Control.Monad.Extra (whenJust)
56
import qualified Data.Aeson as JSON
7+
import Foreign.C.Error (Errno (..), eMFILE)
8+
import GHC.IO.Exception
69
import qualified Network.HTTP.Types.Status as HTTP
10+
import Network.Socket hiding (addrFamily)
11+
import Network.Socket.ByteString
712
import qualified Network.Wai as Wai
813
import qualified Network.Wai.Handler.Warp as Warp
914

10-
import Control.Monad.Extra (whenJust)
11-
import Network.Socket hiding (addrFamily)
12-
import Network.Socket.ByteString
13-
1415
import PostgREST.AppState (AppState, getConfig)
1516
import PostgREST.Config (AppConfig (..))
1617
import PostgREST.MediaType (MediaType (..), toContentType)
@@ -35,9 +36,23 @@ runAdmin appState maybeAdminSocket getSocketREST settings = do
3536
observer = AppState.getObserver appState
3637
adminServerSettings config addr=
3738
settings
39+
& Warp.setAccept safeAccept
3840
& Warp.setBeforeMainLoop (observer $ AdminStartObs addr)
3941
& maybe identity Warp.setPort (configAdminServerPort config)
4042

43+
isEMFILE = (Just eMFILE ==) . fmap Errno . ioe_errno
44+
safeAccept sock =
45+
-- TODO use catchNoPropagate and rethrowIO once
46+
-- we stop supporting GHC versions < 9.12.1
47+
accept sock `catch`
48+
\e ->
49+
if isEMFILE e then
50+
-- Keep accepting on eMFILE
51+
-- TODO log observation???
52+
safeAccept sock
53+
else
54+
throwIO e
55+
4156
onError adminSock ex = do
4257
observer $ AdminServerCrashedObs ex
4358
NS.close adminSock -- we close the socket so request doesn't hang

0 commit comments

Comments
 (0)