Add support for runtime arguments in injection points

The macros INJECTION_POINT() and INJECTION_POINT_CACHED() are extended
with an optional argument that can be passed down to the callback
attached when an injection point is run, giving to callbacks the
possibility to manipulate a stack state given by the caller.  The
existing callbacks in modules injection_points and test_aio have their
declarations adjusted based on that.

da7226993fd4 (core AIO infrastructure) and 93bc3d75d8e1 (test_aio) and
been relying on a set of workarounds where a static variable called
pgaio_inj_cur_handle is used as runtime argument in the injection point
callbacks used by the AIO tests, in combination with a TRY/CATCH block
to reset the argument value.  The infrastructure introduced in this
commit will be reused for the AIO tests, simplifying them.

Reviewed-by: Greg Burd <greg@burd.me>
Discussion: https://postgr.es/m/Z_y9TtnXubvYAApS@paquier.xyz
This commit is contained in:
Michael Paquier 2025-05-10 06:56:26 +09:00
parent 89372d0aaa
commit 371f2db8b0
23 changed files with 69 additions and 57 deletions

View File

@ -3829,15 +3829,17 @@ uint32 WaitEventExtensionNew(const char *wait_event_name)
An injection point with a given <literal>name</literal> is declared using An injection point with a given <literal>name</literal> is declared using
macro: macro:
<programlisting> <programlisting>
INJECTION_POINT(name); INJECTION_POINT(name, arg);
</programlisting> </programlisting>
There are a few injection points already declared at strategic points There are a few injection points already declared at strategic points
within the server code. After adding a new injection point the code needs within the server code. After adding a new injection point the code needs
to be compiled in order for that injection point to be available in the to be compiled in order for that injection point to be available in the
binary. Add-ins written in C-language can declare injection points in binary. Add-ins written in C-language can declare injection points in
their own code using the same macro. The injection point names should their own code using the same macro. The injection point names should use
use lower-case characters, with terms separated by dashes. lower-case characters, with terms separated by
dashes. <literal>arg</literal> is an optional argument value given to the
callback at run-time.
</para> </para>
<para> <para>
@ -3847,7 +3849,7 @@ INJECTION_POINT(name);
a two-step approach with the following macros: a two-step approach with the following macros:
<programlisting> <programlisting>
INJECTION_POINT_LOAD(name); INJECTION_POINT_LOAD(name);
INJECTION_POINT_CACHED(name); INJECTION_POINT_CACHED(name, arg);
</programlisting> </programlisting>
Before entering the critical section, Before entering the critical section,
@ -3880,7 +3882,9 @@ extern void InjectionPointAttach(const char *name,
<literal>InjectionPointCallback</literal>: <literal>InjectionPointCallback</literal>:
<programlisting> <programlisting>
static void static void
custom_injection_callback(const char *name, const void *private_data) custom_injection_callback(const char *name,
const void *private_data,
void *arg)
{ {
uint32 wait_event_info = WaitEventInjectionPointNew(name); uint32 wait_event_info = WaitEventInjectionPointNew(name);
@ -3909,7 +3913,7 @@ if (IS_INJECTION_POINT_ATTACHED("before-foobar"))
local_var = 123; local_var = 123;
/* also execute the callback */ /* also execute the callback */
INJECTION_POINT_CACHED("before-foobar"); INJECTION_POINT_CACHED("before-foobar", NULL);
} }
#endif #endif
</programlisting> </programlisting>

View File

@ -685,9 +685,9 @@ ginFinishSplit(GinBtree btree, GinBtreeStack *stack, bool freestack,
#ifdef USE_INJECTION_POINTS #ifdef USE_INJECTION_POINTS
if (GinPageIsLeaf(BufferGetPage(stack->buffer))) if (GinPageIsLeaf(BufferGetPage(stack->buffer)))
INJECTION_POINT("gin-leave-leaf-split-incomplete"); INJECTION_POINT("gin-leave-leaf-split-incomplete", NULL);
else else
INJECTION_POINT("gin-leave-internal-split-incomplete"); INJECTION_POINT("gin-leave-internal-split-incomplete", NULL);
#endif #endif
/* search parent to lock */ /* search parent to lock */
@ -778,7 +778,7 @@ ginFinishSplit(GinBtree btree, GinBtreeStack *stack, bool freestack,
static void static void
ginFinishOldSplit(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats, int access) ginFinishOldSplit(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats, int access)
{ {
INJECTION_POINT("gin-finish-incomplete-split"); INJECTION_POINT("gin-finish-incomplete-split", NULL);
elog(DEBUG1, "finishing incomplete split of block %u in gin index \"%s\"", elog(DEBUG1, "finishing incomplete split of block %u in gin index \"%s\"",
stack->blkno, RelationGetRelationName(btree->index)); stack->blkno, RelationGetRelationName(btree->index));

View File

@ -3304,7 +3304,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
interesting_attrs = bms_add_members(interesting_attrs, id_attrs); interesting_attrs = bms_add_members(interesting_attrs, id_attrs);
block = ItemPointerGetBlockNumber(otid); block = ItemPointerGetBlockNumber(otid);
INJECTION_POINT("heap_update-before-pin"); INJECTION_POINT("heap_update-before-pin", NULL);
buffer = ReadBuffer(relation, block); buffer = ReadBuffer(relation, block);
page = BufferGetPage(buffer); page = BufferGetPage(buffer);

View File

@ -851,7 +851,7 @@ systable_inplace_update_begin(Relation relation,
if (retries++ > 10000) if (retries++ > 10000)
elog(ERROR, "giving up after too many tries to overwrite row"); elog(ERROR, "giving up after too many tries to overwrite row");
INJECTION_POINT("inplace-before-pin"); INJECTION_POINT("inplace-before-pin", NULL);
scan = systable_beginscan(relation, indexId, indexOK, snapshot, scan = systable_beginscan(relation, indexId, indexOK, snapshot,
nkeys, unconstify(ScanKeyData *, key)); nkeys, unconstify(ScanKeyData *, key));
oldtup = systable_getnext(scan); oldtup = systable_getnext(scan);

View File

@ -872,7 +872,7 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
*/ */
multi = GetNewMultiXactId(nmembers, &offset); multi = GetNewMultiXactId(nmembers, &offset);
INJECTION_POINT_CACHED("multixact-create-from-members"); INJECTION_POINT_CACHED("multixact-create-from-members", NULL);
/* Make an XLOG entry describing the new MXID. */ /* Make an XLOG entry describing the new MXID. */
xlrec.mid = multi; xlrec.mid = multi;
@ -1486,7 +1486,7 @@ retry:
LWLockRelease(lock); LWLockRelease(lock);
CHECK_FOR_INTERRUPTS(); CHECK_FOR_INTERRUPTS();
INJECTION_POINT("multixact-get-members-cv-sleep"); INJECTION_POINT("multixact-get-members-cv-sleep", NULL);
ConditionVariableSleep(&MultiXactState->nextoff_cv, ConditionVariableSleep(&MultiXactState->nextoff_cv,
WAIT_EVENT_MULTIXACT_CREATION); WAIT_EVENT_MULTIXACT_CREATION);

View File

@ -7882,7 +7882,7 @@ CreateRestartPoint(int flags)
* This location needs to be after CheckPointGuts() to ensure that some * This location needs to be after CheckPointGuts() to ensure that some
* work has already happened during this checkpoint. * work has already happened during this checkpoint.
*/ */
INJECTION_POINT("create-restart-point"); INJECTION_POINT("create-restart-point", NULL);
/* /*
* Remember the prior checkpoint's redo ptr for * Remember the prior checkpoint's redo ptr for

View File

@ -3892,9 +3892,9 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
#ifdef USE_INJECTION_POINTS #ifdef USE_INJECTION_POINTS
if (idx->safe) if (idx->safe)
INJECTION_POINT("reindex-conc-index-safe"); INJECTION_POINT("reindex-conc-index-safe", NULL);
else else
INJECTION_POINT("reindex-conc-index-not-safe"); INJECTION_POINT("reindex-conc-index-not-safe", NULL);
#endif #endif
idx->tableId = RelationGetRelid(heapRel); idx->tableId = RelationGetRelid(heapRel);

View File

@ -1492,7 +1492,7 @@ build_hash_tables(AggState *aggstate)
if (IS_INJECTION_POINT_ATTACHED("hash-aggregate-oversize-table")) if (IS_INJECTION_POINT_ATTACHED("hash-aggregate-oversize-table"))
{ {
nbuckets = memory / TupleHashEntrySize(); nbuckets = memory / TupleHashEntrySize();
INJECTION_POINT_CACHED("hash-aggregate-oversize-table"); INJECTION_POINT_CACHED("hash-aggregate-oversize-table", NULL);
} }
#endif #endif
@ -1882,7 +1882,7 @@ hash_agg_check_limits(AggState *aggstate)
if (IS_INJECTION_POINT_ATTACHED("hash-aggregate-spill-1000")) if (IS_INJECTION_POINT_ATTACHED("hash-aggregate-spill-1000"))
{ {
do_spill = true; do_spill = true;
INJECTION_POINT_CACHED("hash-aggregate-spill-1000"); INJECTION_POINT_CACHED("hash-aggregate-spill-1000", NULL);
} }
} }
#endif #endif
@ -1910,7 +1910,7 @@ hash_agg_check_limits(AggState *aggstate)
static void static void
hash_agg_enter_spill_mode(AggState *aggstate) hash_agg_enter_spill_mode(AggState *aggstate)
{ {
INJECTION_POINT("hash-aggregate-enter-spill-mode"); INJECTION_POINT("hash-aggregate-enter-spill-mode", NULL);
aggstate->hash_spill_mode = true; aggstate->hash_spill_mode = true;
hashagg_recompile_expressions(aggstate, aggstate->table_filled, true); hashagg_recompile_expressions(aggstate, aggstate->table_filled, true);
@ -2739,7 +2739,7 @@ agg_refill_hash_table(AggState *aggstate)
*/ */
hashagg_recompile_expressions(aggstate, true, true); hashagg_recompile_expressions(aggstate, true, true);
INJECTION_POINT("hash-aggregate-process-batch"); INJECTION_POINT("hash-aggregate-process-batch", NULL);
for (;;) for (;;)
{ {
TupleTableSlot *spillslot = aggstate->hash_spill_rslot; TupleTableSlot *spillslot = aggstate->hash_spill_rslot;
@ -2995,7 +2995,7 @@ hashagg_spill_init(HashAggSpill *spill, LogicalTapeSet *tapeset, int used_bits,
{ {
npartitions = 1; npartitions = 1;
partition_bits = 0; partition_bits = 0;
INJECTION_POINT_CACHED("hash-aggregate-single-partition"); INJECTION_POINT_CACHED("hash-aggregate-single-partition", NULL);
} }
#endif #endif

View File

@ -500,7 +500,7 @@ secure_open_gssapi(Port *port)
minor; minor;
gss_cred_id_t delegated_creds; gss_cred_id_t delegated_creds;
INJECTION_POINT("backend-gssapi-startup"); INJECTION_POINT("backend-gssapi-startup", NULL);
/* /*
* Allocate subsidiary Port data for GSSAPI operations. * Allocate subsidiary Port data for GSSAPI operations.

View File

@ -131,7 +131,7 @@ secure_open_server(Port *port)
} }
Assert(pq_buffer_remaining_data() == 0); Assert(pq_buffer_remaining_data() == 0);
INJECTION_POINT("backend-ssl-startup"); INJECTION_POINT("backend-ssl-startup", NULL);
r = be_tls_open_server(port); r = be_tls_open_server(port);

View File

@ -1922,7 +1922,7 @@ do_autovacuum(void)
* This injection point is put in a transaction block to work with a wait * This injection point is put in a transaction block to work with a wait
* that uses a condition variable. * that uses a condition variable.
*/ */
INJECTION_POINT("autovacuum-worker-start"); INJECTION_POINT("autovacuum-worker-start", NULL);
/* /*
* Compute the multixact age for which freezing is urgent. This is * Compute the multixact age for which freezing is urgent. This is

View File

@ -1275,7 +1275,7 @@ pgaio_io_call_inj(PgAioHandle *ioh, const char *injection_point)
PG_TRY(); PG_TRY();
{ {
InjectionPointCached(injection_point); InjectionPointCached(injection_point, NULL);
} }
PG_FINALLY(); PG_FINALLY();
{ {

View File

@ -234,7 +234,7 @@ BackendInitialize(ClientSocket *client_sock, CAC_state cac)
/* For testing client error handling */ /* For testing client error handling */
#ifdef USE_INJECTION_POINTS #ifdef USE_INJECTION_POINTS
INJECTION_POINT("backend-initialize"); INJECTION_POINT("backend-initialize", NULL);
if (IS_INJECTION_POINT_ATTACHED("backend-initialize-v2-error")) if (IS_INJECTION_POINT_ATTACHED("backend-initialize-v2-error"))
{ {
/* /*

View File

@ -3482,7 +3482,7 @@ ProcessInterrupts(void)
IdleInTransactionSessionTimeoutPending = false; IdleInTransactionSessionTimeoutPending = false;
if (IdleInTransactionSessionTimeout > 0) if (IdleInTransactionSessionTimeout > 0)
{ {
INJECTION_POINT("idle-in-transaction-session-timeout"); INJECTION_POINT("idle-in-transaction-session-timeout", NULL);
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT), (errcode(ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT),
errmsg("terminating connection due to idle-in-transaction timeout"))); errmsg("terminating connection due to idle-in-transaction timeout")));
@ -3495,7 +3495,7 @@ ProcessInterrupts(void)
TransactionTimeoutPending = false; TransactionTimeoutPending = false;
if (TransactionTimeout > 0) if (TransactionTimeout > 0)
{ {
INJECTION_POINT("transaction-timeout"); INJECTION_POINT("transaction-timeout", NULL);
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_TRANSACTION_TIMEOUT), (errcode(ERRCODE_TRANSACTION_TIMEOUT),
errmsg("terminating connection due to transaction timeout"))); errmsg("terminating connection due to transaction timeout")));
@ -3508,7 +3508,7 @@ ProcessInterrupts(void)
IdleSessionTimeoutPending = false; IdleSessionTimeoutPending = false;
if (IdleSessionTimeout > 0) if (IdleSessionTimeout > 0)
{ {
INJECTION_POINT("idle-session-timeout"); INJECTION_POINT("idle-session-timeout", NULL);
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_IDLE_SESSION_TIMEOUT), (errcode(ERRCODE_IDLE_SESSION_TIMEOUT),
errmsg("terminating connection due to idle-session timeout"))); errmsg("terminating connection due to idle-session timeout")));

View File

@ -1926,7 +1926,7 @@ SearchCatCacheList(CatCache *cache,
/* Injection point to help testing the recursive invalidation case */ /* Injection point to help testing the recursive invalidation case */
if (first_iter) if (first_iter)
{ {
INJECTION_POINT("catcache-list-miss-systable-scan-started"); INJECTION_POINT("catcache-list-miss-systable-scan-started", NULL);
first_iter = false; first_iter = false;
} }

View File

@ -1207,7 +1207,7 @@ AtEOXact_Inval(bool isCommit)
/* Must be at top of stack */ /* Must be at top of stack */
Assert(transInvalInfo->my_level == 1 && transInvalInfo->parent == NULL); Assert(transInvalInfo->my_level == 1 && transInvalInfo->parent == NULL);
INJECTION_POINT("transaction-end-process-inval"); INJECTION_POINT("transaction-end-process-inval", NULL);
if (isCommit) if (isCommit)
{ {

View File

@ -952,7 +952,7 @@ lookup_type_cache(Oid type_id, int flags)
load_domaintype_info(typentry); load_domaintype_info(typentry);
} }
INJECTION_POINT("typecache-before-rel-type-cache-insert"); INJECTION_POINT("typecache-before-rel-type-cache-insert", NULL);
Assert(in_progress_offset + 1 == in_progress_list_len); Assert(in_progress_offset + 1 == in_progress_list_len);
in_progress_list_len--; in_progress_list_len--;

View File

@ -747,7 +747,7 @@ InitPostgres(const char *in_dbname, Oid dboid,
if (!bootstrap) if (!bootstrap)
{ {
pgstat_bestart_initial(); pgstat_bestart_initial();
INJECTION_POINT("init-pre-auth"); INJECTION_POINT("init-pre-auth", NULL);
} }
/* /*

View File

@ -541,14 +541,14 @@ InjectionPointLoad(const char *name)
* Execute an injection point, if defined. * Execute an injection point, if defined.
*/ */
void void
InjectionPointRun(const char *name) InjectionPointRun(const char *name, void *arg)
{ {
#ifdef USE_INJECTION_POINTS #ifdef USE_INJECTION_POINTS
InjectionPointCacheEntry *cache_entry; InjectionPointCacheEntry *cache_entry;
cache_entry = InjectionPointCacheRefresh(name); cache_entry = InjectionPointCacheRefresh(name);
if (cache_entry) if (cache_entry)
cache_entry->callback(name, cache_entry->private_data); cache_entry->callback(name, cache_entry->private_data, arg);
#else #else
elog(ERROR, "Injection points are not supported by this build"); elog(ERROR, "Injection points are not supported by this build");
#endif #endif
@ -558,14 +558,14 @@ InjectionPointRun(const char *name)
* Execute an injection point directly from the cache, if defined. * Execute an injection point directly from the cache, if defined.
*/ */
void void
InjectionPointCached(const char *name) InjectionPointCached(const char *name, void *arg)
{ {
#ifdef USE_INJECTION_POINTS #ifdef USE_INJECTION_POINTS
InjectionPointCacheEntry *cache_entry; InjectionPointCacheEntry *cache_entry;
cache_entry = injection_point_cache_get(name); cache_entry = injection_point_cache_get(name);
if (cache_entry) if (cache_entry)
cache_entry->callback(name, cache_entry->private_data); cache_entry->callback(name, cache_entry->private_data, arg);
#else #else
elog(ERROR, "Injection points are not supported by this build"); elog(ERROR, "Injection points are not supported by this build");
#endif #endif

View File

@ -16,13 +16,13 @@
*/ */
#ifdef USE_INJECTION_POINTS #ifdef USE_INJECTION_POINTS
#define INJECTION_POINT_LOAD(name) InjectionPointLoad(name) #define INJECTION_POINT_LOAD(name) InjectionPointLoad(name)
#define INJECTION_POINT(name) InjectionPointRun(name) #define INJECTION_POINT(name, arg) InjectionPointRun(name, arg)
#define INJECTION_POINT_CACHED(name) InjectionPointCached(name) #define INJECTION_POINT_CACHED(name, arg) InjectionPointCached(name, arg)
#define IS_INJECTION_POINT_ATTACHED(name) IsInjectionPointAttached(name) #define IS_INJECTION_POINT_ATTACHED(name) IsInjectionPointAttached(name)
#else #else
#define INJECTION_POINT_LOAD(name) ((void) name) #define INJECTION_POINT_LOAD(name) ((void) name)
#define INJECTION_POINT(name) ((void) name) #define INJECTION_POINT(name, arg) ((void) name)
#define INJECTION_POINT_CACHED(name) ((void) name) #define INJECTION_POINT_CACHED(name, arg) ((void) name)
#define IS_INJECTION_POINT_ATTACHED(name) (false) #define IS_INJECTION_POINT_ATTACHED(name) (false)
#endif #endif
@ -30,7 +30,8 @@
* Typedef for callback function launched by an injection point. * Typedef for callback function launched by an injection point.
*/ */
typedef void (*InjectionPointCallback) (const char *name, typedef void (*InjectionPointCallback) (const char *name,
const void *private_data); const void *private_data,
void *arg);
extern Size InjectionPointShmemSize(void); extern Size InjectionPointShmemSize(void);
extern void InjectionPointShmemInit(void); extern void InjectionPointShmemInit(void);
@ -41,8 +42,8 @@ extern void InjectionPointAttach(const char *name,
const void *private_data, const void *private_data,
int private_data_size); int private_data_size);
extern void InjectionPointLoad(const char *name); extern void InjectionPointLoad(const char *name);
extern void InjectionPointRun(const char *name); extern void InjectionPointRun(const char *name, void *arg);
extern void InjectionPointCached(const char *name); extern void InjectionPointCached(const char *name, void *arg);
extern bool IsInjectionPointAttached(const char *name); extern bool IsInjectionPointAttached(const char *name);
extern bool InjectionPointDetach(const char *name); extern bool InjectionPointDetach(const char *name);

View File

@ -94,11 +94,14 @@ typedef struct InjectionPointSharedState
static InjectionPointSharedState *inj_state = NULL; static InjectionPointSharedState *inj_state = NULL;
extern PGDLLEXPORT void injection_error(const char *name, extern PGDLLEXPORT void injection_error(const char *name,
const void *private_data); const void *private_data,
void *arg);
extern PGDLLEXPORT void injection_notice(const char *name, extern PGDLLEXPORT void injection_notice(const char *name,
const void *private_data); const void *private_data,
void *arg);
extern PGDLLEXPORT void injection_wait(const char *name, extern PGDLLEXPORT void injection_wait(const char *name,
const void *private_data); const void *private_data,
void *arg);
/* track if injection points attached in this process are linked to it */ /* track if injection points attached in this process are linked to it */
static bool injection_point_local = false; static bool injection_point_local = false;
@ -239,7 +242,7 @@ injection_points_cleanup(int code, Datum arg)
/* Set of callbacks available to be attached to an injection point. */ /* Set of callbacks available to be attached to an injection point. */
void void
injection_error(const char *name, const void *private_data) injection_error(const char *name, const void *private_data, void *arg)
{ {
InjectionPointCondition *condition = (InjectionPointCondition *) private_data; InjectionPointCondition *condition = (InjectionPointCondition *) private_data;
@ -252,7 +255,7 @@ injection_error(const char *name, const void *private_data)
} }
void void
injection_notice(const char *name, const void *private_data) injection_notice(const char *name, const void *private_data, void *arg)
{ {
InjectionPointCondition *condition = (InjectionPointCondition *) private_data; InjectionPointCondition *condition = (InjectionPointCondition *) private_data;
@ -266,7 +269,7 @@ injection_notice(const char *name, const void *private_data)
/* Wait on a condition variable, awaken by injection_points_wakeup() */ /* Wait on a condition variable, awaken by injection_points_wakeup() */
void void
injection_wait(const char *name, const void *private_data) injection_wait(const char *name, const void *private_data, void *arg)
{ {
uint32 old_wait_counts = 0; uint32 old_wait_counts = 0;
int index = -1; int index = -1;
@ -405,7 +408,7 @@ injection_points_run(PG_FUNCTION_ARGS)
char *name = text_to_cstring(PG_GETARG_TEXT_PP(0)); char *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
pgstat_report_inj_fixed(0, 0, 1, 0, 0); pgstat_report_inj_fixed(0, 0, 1, 0, 0);
INJECTION_POINT(name); INJECTION_POINT(name, NULL);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
@ -420,7 +423,7 @@ injection_points_cached(PG_FUNCTION_ARGS)
char *name = text_to_cstring(PG_GETARG_TEXT_PP(0)); char *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
pgstat_report_inj_fixed(0, 0, 0, 1, 0); pgstat_report_inj_fixed(0, 0, 0, 1, 0);
INJECTION_POINT_CACHED(name); INJECTION_POINT_CACHED(name, NULL);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }

View File

@ -674,11 +674,15 @@ batch_end(PG_FUNCTION_ARGS)
} }
#ifdef USE_INJECTION_POINTS #ifdef USE_INJECTION_POINTS
extern PGDLLEXPORT void inj_io_short_read(const char *name, const void *private_data); extern PGDLLEXPORT void inj_io_short_read(const char *name,
extern PGDLLEXPORT void inj_io_reopen(const char *name, const void *private_data); const void *private_data,
void *arg);
extern PGDLLEXPORT void inj_io_reopen(const char *name,
const void *private_data,
void *arg);
void void
inj_io_short_read(const char *name, const void *private_data) inj_io_short_read(const char *name, const void *private_data, void *arg)
{ {
PgAioHandle *ioh; PgAioHandle *ioh;
@ -742,7 +746,7 @@ inj_io_short_read(const char *name, const void *private_data)
} }
void void
inj_io_reopen(const char *name, const void *private_data) inj_io_reopen(const char *name, const void *private_data, void *arg)
{ {
ereport(LOG, ereport(LOG,
errmsg("reopen injection point called, is enabled: %d", errmsg("reopen injection point called, is enabled: %d",

View File

@ -46,7 +46,7 @@ test_read_multixact(PG_FUNCTION_ARGS)
MultiXactId id = PG_GETARG_TRANSACTIONID(0); MultiXactId id = PG_GETARG_TRANSACTIONID(0);
MultiXactMember *members; MultiXactMember *members;
INJECTION_POINT("test-multixact-read"); INJECTION_POINT("test-multixact-read", NULL);
/* discard caches */ /* discard caches */
AtEOXact_MultiXact(); AtEOXact_MultiXact();