├── .editorconfig ├── LICENSE ├── Makefile ├── README.md ├── debian ├── changelog ├── control ├── control.in ├── copyright ├── gitlab-ci.yml ├── pgversions ├── rules ├── source │ └── format ├── tests │ ├── control │ └── crash └── watch ├── pg_crash.c └── pg_crash.spec /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_size = tab 5 | 6 | [*] 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | indent_style = unset 10 | tab_width = unset 11 | 12 | [*.[chly]] 13 | trim_trailing_whitespace = true 14 | insert_final_newline = true 15 | indent_style = tab 16 | tab_width = 4 17 | 18 | [*.out] 19 | indent_style = unset 20 | indent_size = unset 21 | trim_trailing_whitespace = unset 22 | insert_final_newline = unset 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, 2025 CYBERTEC PostgreSQL International GmbH 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MODULE_big = pg_crash 2 | OBJS = pg_crash.o $(WIN32RES) 3 | PGFILEDESC = "pg_crash" 4 | 5 | PG_CONFIG = pg_config 6 | PGXS := $(shell $(PG_CONFIG) --pgxs) 7 | include $(PGXS) 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pg\_crash 2 | 3 | If your database is too reliable - pg\_crash can kill it for you. pg\_crash is 4 | an extension to PostgreSQL, which allows you to periodically or randomly crash 5 | your database infrastructure by sending kill (or other) signals to your DB 6 | processes and make them fail. It is ideal for HA and failover testing. 7 | 8 | Works with Postgres >= 11. 9 | 10 | # Installation 11 | 12 | * Build the extension 13 | 14 | ``` 15 | PG_CONFIG=/usr/local/pgsql/bin/pg_config make 16 | sudo PG_CONFIG=/usr/local/pgsql/bin/pg_config make install 17 | ``` 18 | NB! Replace /usr/local/pgsql/bin with your desired binary 19 | 20 | * Edit server config 21 | 22 | Add 'pg\_crash to shared\_preload\_libraries and configure signals and timeouts 23 | 24 | ``` 25 | shared_preload_libraries = ',pg_crash' 26 | # any POSIX signals you want to emit from the background worker 27 | crash.signals = '1 2 3' 28 | # set delay (in seconds) between sending signals 29 | crash.delay = 30 30 | ``` 31 | 32 | * restart the server 33 | 34 | ## Have fun troubleshooting! 35 | 36 | ### Developer Credits 37 | 38 | Antonin Houska, CYBERTEC PostgreSQL International GmbH. 39 | Visit our website: [www.cybertec-postgresql.com](https://www.cybertec-postgresql.com) 40 | 41 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | pg-crash (0.3-1) unstable; urgency=medium 2 | 3 | * New upstream version. 4 | 5 | -- Christoph Berg Fri, 13 Jun 2025 16:54:40 +0200 6 | 7 | pg-crash (0.2-1) unstable; urgency=medium 8 | 9 | * Initial release. 10 | 11 | -- Christoph Berg Thu, 12 Jun 2025 16:44:40 +0200 12 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: pg-crash 2 | Section: database 3 | Priority: optional 4 | Maintainer: Debian PostgreSQL Maintainers 5 | Uploaders: 6 | Christoph Berg , 7 | Build-Depends: 8 | architecture-is-64-bit , 9 | debhelper-compat (= 13), 10 | postgresql-all , 11 | postgresql-server-dev-all (>= 217~), 12 | Standards-Version: 4.7.2 13 | Rules-Requires-Root: no 14 | Homepage: https://github.com/cybertec-postgresql/pg_crash 15 | Vcs-Browser: https://salsa.debian.org/postgresql/pg-crash 16 | Vcs-Git: https://salsa.debian.org/postgresql/pg-crash.git 17 | 18 | Package: postgresql-17-pg-crash 19 | Architecture: any 20 | Depends: 21 | ${misc:Depends}, 22 | ${postgresql:Depends}, 23 | ${shlibs:Depends}, 24 | Description: Periodically crash your PostgreSQL database 25 | If your database is too reliable - pg_crash can kill it for you. pg_crash is 26 | an extension to PostgreSQL that periodically crashes your database 27 | infrastructure by sending kill (or other) signals to your DB processes and 28 | make them fail. It is ideal for HA and failover testing. 29 | -------------------------------------------------------------------------------- /debian/control.in: -------------------------------------------------------------------------------- 1 | Source: pg-crash 2 | Section: database 3 | Priority: optional 4 | Maintainer: Debian PostgreSQL Maintainers 5 | Uploaders: 6 | Christoph Berg , 7 | Build-Depends: 8 | architecture-is-64-bit , 9 | debhelper-compat (= 13), 10 | postgresql-all , 11 | postgresql-server-dev-all (>= 217~), 12 | Standards-Version: 4.7.2 13 | Rules-Requires-Root: no 14 | Homepage: https://github.com/cybertec-postgresql/pg_crash 15 | Vcs-Browser: https://salsa.debian.org/postgresql/pg-crash 16 | Vcs-Git: https://salsa.debian.org/postgresql/pg-crash.git 17 | 18 | Package: postgresql-PGVERSION-pg-crash 19 | Architecture: any 20 | Depends: 21 | ${misc:Depends}, 22 | ${postgresql:Depends}, 23 | ${shlibs:Depends}, 24 | Description: Periodically crash your PostgreSQL database 25 | If your database is too reliable - pg_crash can kill it for you. pg_crash is 26 | an extension to PostgreSQL that periodically crashes your database 27 | infrastructure by sending kill (or other) signals to your DB processes and 28 | make them fail. It is ideal for HA and failover testing. 29 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: pg-crash 3 | Source: https://github.com/cybertec-postgresql/pg_crash 4 | 5 | Files: * 6 | Copyright: 7 | Copyright (c) 2017, 2025 CYBERTEC PostgreSQL International GmbH 8 | License: BSD 9 | All rights reserved. 10 | . 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | . 14 | * Redistributions of source code must retain the above copyright notice, this 15 | list of conditions and the following disclaimer. 16 | . 17 | * Redistributions in binary form must reproduce the above copyright notice, 18 | this list of conditions and the following disclaimer in the documentation 19 | and/or other materials provided with the distribution. 20 | . 21 | * Neither the name of the copyright holder nor the names of its 22 | contributors may be used to endorse or promote products derived from 23 | this software without specific prior written permission. 24 | . 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | -------------------------------------------------------------------------------- /debian/gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | include: https://salsa.debian.org/postgresql/postgresql-common/raw/master/gitlab/gitlab-ci.yml 2 | -------------------------------------------------------------------------------- /debian/pgversions: -------------------------------------------------------------------------------- 1 | 11+ 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | %: 4 | dh $@ --with pgxs 5 | 6 | override_dh_pgxs_test: 7 | debian/tests/crash . . postgresql-%v-pg-crash 8 | 9 | override_dh_installdocs: 10 | dh_installdocs --all README.* 11 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /debian/tests/control: -------------------------------------------------------------------------------- 1 | Depends: 2 | postgresql-common-dev, 3 | @, 4 | Tests: crash 5 | Restrictions: allow-stderr 6 | -------------------------------------------------------------------------------- /debian/tests/crash: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | export LC_ALL=C.UTF-8 6 | 7 | echo "psql -Xc 'SELECT pg_sleep(600)' 2>&1 | grep 'FATAL: terminating connection due to administrator command'" | \ 8 | pg_buildext \ 9 | -o "shared_preload_libraries=pg_crash" \ 10 | -o "superuser_reserved_connections=0" \ 11 | -o "max_wal_senders=0" \ 12 | -o "max_connections=1" \ 13 | virtualenv "$@" 14 | -------------------------------------------------------------------------------- /debian/watch: -------------------------------------------------------------------------------- 1 | version=4 2 | https://github.com/cybertec-postgresql/pg_crash/tags .*/v?(.*).tar.gz 3 | -------------------------------------------------------------------------------- /pg_crash.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "c.h" 4 | #include "postgres.h" 5 | #include "fmgr.h" 6 | #include "miscadmin.h" 7 | #include "access/twophase.h" 8 | #include "catalog/pg_control.h" 9 | #include "postmaster/bgworker.h" 10 | #include "storage/proc.h" 11 | #include "utils/guc.h" 12 | 13 | PG_MODULE_MAGIC; 14 | 15 | extern void _PG_init(void); 16 | PGDLLEXPORT extern void crash_worker_main(Datum main_arg); 17 | 18 | static int signal_delay; 19 | static char *crash_signals; 20 | static List *signals = NIL; 21 | 22 | void 23 | _PG_init(void) 24 | { 25 | BackgroundWorker worker; 26 | 27 | DefineCustomIntVariable( 28 | "crash.delay", 29 | "Sleep time (in seconds) of the crash worker.", 30 | "Sleep this many seconds before sending the next signal.", 31 | &signal_delay, 32 | 1, 1, INT_MAX, 33 | PGC_POSTMASTER, 34 | GUC_UNIT_S, 35 | NULL, NULL, NULL); 36 | 37 | DefineCustomStringVariable( 38 | "crash.signals", 39 | "A list of signals to choose from.", 40 | "Random signal is chosen out of the ones contained in the set (space-separated).", 41 | &crash_signals, 42 | "15", 43 | PGC_POSTMASTER, 44 | 0, 45 | NULL, NULL, NULL); 46 | 47 | worker.bgw_flags = BGWORKER_SHMEM_ACCESS; 48 | worker.bgw_start_time = BgWorkerStart_RecoveryFinished; 49 | worker.bgw_restart_time = 0; 50 | sprintf(worker.bgw_type, "crash worker"); 51 | sprintf(worker.bgw_name, "crash worker"); 52 | sprintf(worker.bgw_library_name, "pg_crash"); 53 | sprintf(worker.bgw_function_name, "crash_worker_main"); 54 | worker.bgw_main_arg = (Datum) 0; 55 | worker.bgw_notify_pid = 0; 56 | RegisterBackgroundWorker(&worker); 57 | } 58 | 59 | static volatile sig_atomic_t got_sigterm = false; 60 | 61 | static void 62 | crash_worker_sigterm(SIGNAL_ARGS) 63 | { 64 | int save_errno = errno; 65 | 66 | got_sigterm = true; 67 | SetLatch(MyLatch); 68 | 69 | errno = save_errno; 70 | } 71 | 72 | void 73 | crash_worker_main(Datum main_arg) 74 | { 75 | uint32 nprocs = MaxBackends + NUM_AUXILIARY_PROCS + max_prepared_xacts; 76 | PGPROC *procs = ProcGlobal->allProcs; 77 | 78 | pqsignal(SIGTERM, crash_worker_sigterm); 79 | BackgroundWorkerUnblockSignals(); 80 | 81 | if (signals == NIL) 82 | { 83 | char *c, *start = NULL; 84 | 85 | /* Parse the list of signals. */ 86 | c = crash_signals; 87 | while (true) 88 | { 89 | /* Looking for the next value? */ 90 | if (isspace(*c) && start == NULL) 91 | { 92 | c++; 93 | /* Done? */ 94 | if (*c == '\0') 95 | break; 96 | continue; 97 | } 98 | 99 | if (start == NULL) 100 | { 101 | start = c++; 102 | continue; 103 | } 104 | else if (isspace(*c) || *c == '\0') 105 | { 106 | Size len = c - start; 107 | char *str = pnstrdup(start, len); 108 | long int nr; 109 | 110 | errno = 0; 111 | nr = strtol(str, NULL, 10); 112 | 113 | if (errno != 0) 114 | ereport(ERROR, 115 | (errmsg("\"%s\" is not a valid integer value", 116 | str))); 117 | pfree(str); 118 | signals = lappend_int(signals, nr); 119 | 120 | if (*c == '\0') 121 | break; 122 | 123 | start = NULL; 124 | } 125 | c++; 126 | } 127 | 128 | if (list_length(signals) == 0) 129 | ereport(ERROR, (errmsg("no signals specified"))); 130 | } 131 | 132 | ereport(LOG, 133 | (errmsg("pg_crash background worker started, crash.delay = %d, crash.signals = '%s'", 134 | signal_delay, crash_signals))); 135 | 136 | for (;;) 137 | { 138 | long int n; 139 | int i, j; 140 | int rc; 141 | int signal; 142 | 143 | /* wait for signal_delay seconds */ 144 | ResetLatch(MyLatch); 145 | 146 | rc = WaitLatch(MyLatch, WL_LATCH_SET | WL_POSTMASTER_DEATH | 147 | WL_TIMEOUT, signal_delay * 1000L, 0); 148 | if (rc & WL_POSTMASTER_DEATH) 149 | break; 150 | 151 | if (got_sigterm) 152 | break; 153 | 154 | /* Select signal. */ 155 | n = rand() % list_length(signals); 156 | signal = list_nth_int(signals, n); 157 | 158 | /* Select backend. */ 159 | n = rand() % nprocs; 160 | j = 0; 161 | for (i = 0;; i++) 162 | { 163 | PGPROC *proc = &procs[i % nprocs]; 164 | 165 | /* 166 | * Do not send signals to the bgworker, otherwise it won't be 167 | * restarted after a crash. 168 | */ 169 | if (proc->pid > 0 && proc->pid != MyProcPid) 170 | { 171 | if (j == n) 172 | { 173 | /* Send the signal. */ 174 | ereport(DEBUG1, 175 | (errmsg("sending signal %d to process %d", 176 | signal, proc->pid))); 177 | kill(proc->pid, signal); 178 | break; 179 | } 180 | j++; 181 | } 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /pg_crash.spec: -------------------------------------------------------------------------------- 1 | %global sname pg_crash 2 | 3 | %{!?llvm:%global llvm 1} 4 | 5 | Summary: Periodically crash your PostgreSQL database 6 | Name: %{sname}_%{pgmajorversion} 7 | Version: 0.3 8 | Release: 1PGDG%{?dist} 9 | License: PostgreSQL 10 | Source0: https://github.com/cybertec-postgresql/%{sname}/archive/refs/tags/v%{version}.tar.gz 11 | URL: https://github.com/cybertec-postgresql/%{sname} 12 | BuildRequires: postgresql%{pgmajorversion}-devel 13 | Requires: postgresql%{pgmajorversion}-server 14 | 15 | %description 16 | If your database is too reliable - pg_crash can kill it for you. pg_crash is 17 | an extension to PostgreSQL that periodically crashes your database 18 | infrastructure by sending kill (or other) signals to your DB processes and 19 | make them fail. It is ideal for HA and failover testing. 20 | 21 | %if %llvm 22 | %package llvmjit 23 | Summary: Just-in-time compilation support for pg_crash 24 | Requires: %{name}%{?_isa} = %{version}-%{release} 25 | %if 0%{?suse_version} >= 1500 26 | BuildRequires: llvm17-devel clang17-devel 27 | Requires: llvm17 28 | %endif 29 | %if 0%{?fedora} || 0%{?rhel} >= 8 30 | BuildRequires: llvm-devel >= 17.0 clang-devel >= 17.0 31 | Requires: llvm => 17.0 32 | %endif 33 | 34 | %description llvmjit 35 | This package provides JIT support for pg_crash 36 | %endif 37 | 38 | %prep 39 | %setup -q -n %{sname}-%{version} 40 | 41 | %build 42 | USE_PGXS=1 PATH=%{pginstdir}/bin/:$PATH %{__make} %{?_smp_mflags} 43 | 44 | %install 45 | %{__rm} -rf %{buildroot} 46 | USE_PGXS=1 PATH=%{pginstdir}/bin/:$PATH %{__make} %{?_smp_mflags} install DESTDIR=%{buildroot} 47 | %{__mkdir} -p %{buildroot}%{pginstdir}/doc/extension/ 48 | %{__cp} README.md %{buildroot}%{pginstdir}/doc/extension/README-%{sname}.md 49 | 50 | %files 51 | %license LICENSE 52 | %doc %{pginstdir}/doc/extension/README-%{sname}.md 53 | %defattr(644,root,root,755) 54 | %{pginstdir}/lib/%{sname}.so 55 | 56 | 57 | %if %llvm 58 | %files llvmjit 59 | %{pginstdir}/lib/bitcode/%{sname}*.bc 60 | %{pginstdir}/lib/bitcode/%{sname}/*.bc 61 | %endif 62 | 63 | %changelog 64 | * Fri Jun 13 2025 Christoph Berg - 0.2-1PGDG 65 | - Initial RPM packaging 66 | --------------------------------------------------------------------------------