1
/*-------------------------------------------------------------------------
4
* Simplistic testbed for shared memory and semaphore code.
6
* This file allows for quick "smoke testing" of a PG semaphore or shared
7
* memory implementation, with less overhead than compiling up a whole
8
* installation. To use:
9
* 1. Run configure, then edit src/include/pg_config.h to select the
10
* USE_xxx_SEMAPHORES and USE_xxx_SHARED_MEMORY settings you want.
11
* Also, adjust the pg_sema.c and pg_shmem.c symlinks in
12
* src/backend/port/ if needed.
13
* 2. In src/backend/port/, do "gmake ipc_test".
14
* 3. Run ipc_test and see if it works.
15
* 4. If it seems to work, try building the whole system and running
16
* the parallel regression tests for a more complete test.
19
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
20
* Portions Copyright (c) 1994, Regents of the University of California
24
* src/backend/port/ipc_test.c
26
*-------------------------------------------------------------------------
32
#include "miscadmin.h"
33
#include "storage/ipc.h"
34
#include "storage/pg_sema.h"
35
#include "storage/pg_shmem.h"
38
/********* stuff needed to satisfy references in shmem/sema code *********/
41
volatile bool InterruptPending = false;
42
volatile bool QueryCancelPending = false;
43
volatile bool ProcDiePending = false;
44
volatile bool ImmediateInterruptOK = false;
45
volatile uint32 InterruptHoldoffCount = 0;
46
volatile uint32 CritSectionCount = 0;
48
bool IsUnderPostmaster = false;
49
bool assert_enabled = true;
57
#define MAX_ON_EXITS 20
61
pg_on_exit_callback function;
63
} on_proc_exit_list[MAX_ON_EXITS], on_shmem_exit_list[MAX_ON_EXITS];
65
static int on_proc_exit_index,
72
while (--on_proc_exit_index >= 0)
73
(*on_proc_exit_list[on_proc_exit_index].function) (code,
74
on_proc_exit_list[on_proc_exit_index].arg);
81
while (--on_shmem_exit_index >= 0)
82
(*on_shmem_exit_list[on_shmem_exit_index].function) (code,
83
on_shmem_exit_list[on_shmem_exit_index].arg);
84
on_shmem_exit_index = 0;
88
on_shmem_exit(pg_on_exit_callback function, Datum arg)
90
if (on_shmem_exit_index >= MAX_ON_EXITS)
91
elog(FATAL, "out of on_shmem_exit slots");
93
on_shmem_exit_list[on_shmem_exit_index].function = function;
94
on_shmem_exit_list[on_shmem_exit_index].arg = arg;
96
++on_shmem_exit_index;
102
on_shmem_exit_index = 0;
103
on_proc_exit_index = 0;
107
AddToDataDirLockFile(int target_line, const char *str)
112
ProcessInterrupts(void)
117
ExceptionalCondition(const char *conditionName,
118
const char *errorType,
119
const char *fileName,
122
fprintf(stderr, "TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n",
123
errorType, conditionName,
124
fileName, lineNumber);
131
errcode_for_file_access(void)
137
errstart(int elevel, const char *filename, int lineno,
138
const char *funcname, const char *domain)
140
return (elevel >= ERROR);
144
errfinish(int dummy,...)
150
elog_start(const char *filename, int lineno, const char *funcname)
155
elog_finish(int elevel, const char *fmt,...)
157
fprintf(stderr, "ERROR: %s\n", fmt);
162
errcode(int sqlerrcode)
164
return 0; /* return value does not matter */
168
errmsg(const char *fmt,...)
170
fprintf(stderr, "ERROR: %s\n", fmt);
171
return 0; /* return value does not matter */
175
errmsg_internal(const char *fmt,...)
177
fprintf(stderr, "ERROR: %s\n", fmt);
178
return 0; /* return value does not matter */
182
errdetail(const char *fmt,...)
184
fprintf(stderr, "DETAIL: %s\n", fmt);
185
return 0; /* return value does not matter */
189
errdetail_log(const char *fmt,...)
191
fprintf(stderr, "DETAIL: %s\n", fmt);
192
return 0; /* return value does not matter */
196
errhint(const char *fmt,...)
198
fprintf(stderr, "HINT: %s\n", fmt);
199
return 0; /* return value does not matter */
203
/********* here's the actual test *********/
206
typedef struct MyStorage
208
PGShmemHeader header;
215
main(int argc, char **argv)
220
printf("Creating shared memory ... ");
223
storage = (MyStorage *) PGSharedMemoryCreate(8192, false, 5433);
225
storage->flag = 1234;
229
printf("Creating semaphores ... ");
232
PGReserveSemaphores(2, 5433);
234
PGSemaphoreCreate(&storage->sem);
238
/* sema initial value is 1, so lock should work */
240
printf("Testing Lock ... ");
243
PGSemaphoreLock(&storage->sem, false);
247
/* now sema value is 0, so trylock should fail */
249
printf("Testing TryLock ... ");
252
if (PGSemaphoreTryLock(&storage->sem))
253
printf("unexpected result!\n");
257
/* unlocking twice and then locking twice should work... */
259
printf("Testing Multiple Lock ... ");
262
PGSemaphoreUnlock(&storage->sem);
263
PGSemaphoreUnlock(&storage->sem);
265
PGSemaphoreLock(&storage->sem, false);
266
PGSemaphoreLock(&storage->sem, false);
270
/* check Reset too */
272
printf("Testing Reset ... ");
275
PGSemaphoreUnlock(&storage->sem);
277
PGSemaphoreReset(&storage->sem);
279
if (PGSemaphoreTryLock(&storage->sem))
280
printf("unexpected result!\n");
284
/* Fork a child process and see if it can communicate */
286
printf("Forking child process ... ");
296
PGSemaphoreUnlock(&storage->sem);
302
printf("failed: %s\n", strerror(errno));
306
printf("forked child pid %d OK\n", cpid);
308
if (storage->flag != 1234)
309
printf("Wrong value found in shared memory!\n");
311
printf("Waiting for child (should wait 3 sec here) ... ");
314
PGSemaphoreLock(&storage->sem, false);
318
if (storage->flag != 1235)
319
printf("Wrong value found in shared memory!\n");
323
printf("Running shmem_exit processing ... ");
330
printf("Tests complete.\n");
334
return 0; /* not reached */