fix: not logging termination unix signals
Under container environments like ECS, it's hard to know when PostgREST is being terminated.
This commit is contained in:
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. From versio
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix not logging SIGTERM and SIGINT by @steve-chavez in #4728
|
||||||
|
|
||||||
## [14.6] - 2026-03-06
|
## [14.6] - 2026-03-06
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ run appState = do
|
|||||||
conf@AppConfig{..} <- AppState.getConfig appState
|
conf@AppConfig{..} <- AppState.getConfig appState
|
||||||
|
|
||||||
AppState.schemaCacheLoader appState -- Loads the initial SchemaCache
|
AppState.schemaCacheLoader appState -- Loads the initial SchemaCache
|
||||||
Unix.installSignalHandlers (AppState.getMainThreadId appState) (AppState.schemaCacheLoader appState) (AppState.readInDbConfig False appState)
|
Unix.installSignalHandlers observer (AppState.getMainThreadId appState) (AppState.schemaCacheLoader appState) (AppState.readInDbConfig False appState)
|
||||||
|
|
||||||
Listener.runListener appState
|
Listener.runListener appState
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ data Observation
|
|||||||
| PoolRequestFullfilled
|
| PoolRequestFullfilled
|
||||||
| JwtCacheLookup Bool
|
| JwtCacheLookup Bool
|
||||||
| JwtCacheEviction
|
| JwtCacheEviction
|
||||||
|
| TerminationUnixSignalObs Text
|
||||||
| WarpErrorObs Text
|
| WarpErrorObs Text
|
||||||
|
|
||||||
data ObsFatalError = ServerAuthError | ServerPgrstBug | ServerError42P05 | ServerError08P01
|
data ObsFatalError = ServerAuthError | ServerPgrstBug | ServerError42P05 | ServerError08P01
|
||||||
@@ -158,6 +159,8 @@ observationMessage = \case
|
|||||||
"Looked up a JWT in JWT cache"
|
"Looked up a JWT in JWT cache"
|
||||||
JwtCacheEviction ->
|
JwtCacheEviction ->
|
||||||
"Evicted entry from JWT cache"
|
"Evicted entry from JWT cache"
|
||||||
|
TerminationUnixSignalObs signal ->
|
||||||
|
"Received termination unix signal " <> signal
|
||||||
WarpErrorObs txt ->
|
WarpErrorObs txt ->
|
||||||
"Warp server error: " <> txt
|
"Warp server error: " <> txt
|
||||||
where
|
where
|
||||||
|
|||||||
+10
-9
@@ -11,26 +11,27 @@ import qualified System.Posix.Signals as Signals
|
|||||||
import System.Posix.Types (FileMode)
|
import System.Posix.Types (FileMode)
|
||||||
import System.PosixCompat.Files (setFileMode)
|
import System.PosixCompat.Files (setFileMode)
|
||||||
|
|
||||||
import Data.String (String)
|
import Data.String (String)
|
||||||
import qualified Network.Socket as NS
|
import qualified Network.Socket as NS
|
||||||
|
import qualified PostgREST.Observation as Observation
|
||||||
import Protolude
|
import Protolude
|
||||||
import System.Directory (removeFile)
|
import System.Directory (removeFile)
|
||||||
import System.IO.Error (isDoesNotExistError)
|
import System.IO.Error (isDoesNotExistError)
|
||||||
|
|
||||||
-- | Set signal handlers, only for systems with signals
|
-- | Set signal handlers, only for systems with signals
|
||||||
installSignalHandlers :: ThreadId -> IO () -> IO () -> IO ()
|
installSignalHandlers :: Observation.ObservationHandler -> ThreadId -> IO () -> IO () -> IO ()
|
||||||
#ifndef mingw32_HOST_OS
|
#ifndef mingw32_HOST_OS
|
||||||
installSignalHandlers tid usr1 usr2 = do
|
installSignalHandlers observer tid usr1 usr2 = do
|
||||||
let interrupt = throwTo tid UserInterrupt
|
let interrupt = throwTo tid UserInterrupt
|
||||||
install Signals.sigINT interrupt
|
install Signals.sigINT $ observer (Observation.TerminationUnixSignalObs "SIGINT") >> interrupt
|
||||||
install Signals.sigTERM interrupt
|
install Signals.sigTERM $ observer (Observation.TerminationUnixSignalObs "SIGTERM") >> interrupt
|
||||||
install Signals.sigUSR1 usr1
|
install Signals.sigUSR1 usr1
|
||||||
install Signals.sigUSR2 usr2
|
install Signals.sigUSR2 usr2
|
||||||
where
|
where
|
||||||
install signal handler =
|
install signal handler =
|
||||||
void $ Signals.installHandler signal (Signals.Catch handler) Nothing
|
void $ Signals.installHandler signal (Signals.Catch handler) Nothing
|
||||||
#else
|
#else
|
||||||
installSignalHandlers _ _ _ = pass
|
installSignalHandlers _ _ _ _ = pass
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
-- | Create a unix domain socket and bind it to the given path.
|
-- | Create a unix domain socket and bind it to the given path.
|
||||||
|
|||||||
@@ -105,6 +105,24 @@ def test_flush_pool_no_interrupt(defaultenv):
|
|||||||
t.join()
|
t.join()
|
||||||
|
|
||||||
|
|
||||||
|
def test_termination_unix_signal_logging(defaultenv):
|
||||||
|
"Server logs when handling termination unix signals."
|
||||||
|
|
||||||
|
with run(env=defaultenv) as postgrest:
|
||||||
|
postgrest.process.send_signal(signal.SIGTERM)
|
||||||
|
lines = postgrest.read_stdout(nlines=1)
|
||||||
|
wait_until_exit(postgrest)
|
||||||
|
|
||||||
|
assert any("SIGTERM" in line for line in lines)
|
||||||
|
|
||||||
|
with run(env=defaultenv) as postgrest:
|
||||||
|
postgrest.process.send_signal(signal.SIGINT)
|
||||||
|
lines = postgrest.read_stdout(nlines=1)
|
||||||
|
wait_until_exit(postgrest)
|
||||||
|
|
||||||
|
assert any("SIGINT" in line for line in lines)
|
||||||
|
|
||||||
|
|
||||||
def test_random_port_bound(defaultenv):
|
def test_random_port_bound(defaultenv):
|
||||||
"PostgREST should bind to a random port when PGRST_SERVER_PORT is 0."
|
"PostgREST should bind to a random port when PGRST_SERVER_PORT is 0."
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user