Example #1
0
void
pool_shmem_exit(int code)
{
	shmem_exit(code);
	/* Close syslog connection here as this function is always called on exit */
	closelog();
}
Example #2
0
void
proc_exit(int code)
{
	shmem_exit(code);
	while (--on_proc_exit_index >= 0)
		(*on_proc_exit_list[on_proc_exit_index].function) (code,
								  on_proc_exit_list[on_proc_exit_index].arg);
	exit(code);
}
Example #3
0
/*
 * Code shared between proc_exit and the atexit handler.  Note that in
 * normal exit through proc_exit, this will actually be called twice ...
 * but the second call will have nothing to do.
 */
static void
proc_exit_prepare(int code)
{
	/*
	 * Once we set this flag, we are committed to exit.  Any ereport() will
	 * NOT send control back to the main loop, but right back here.
	 */
	proc_exit_inprogress = true;

	/*
	 * Forget any pending cancel or die requests; we're doing our best to
	 * close up shop already.  Note that the signal handlers will not set
	 * these flags again, now that proc_exit_inprogress is set.
	 */
	InterruptPending = false;
	ProcDiePending = false;
	QueryCancelPending = false;
	/* And let's just make *sure* we're not interrupted ... */
	ImmediateInterruptOK = false;
	InterruptHoldoffCount = 1;
	CritSectionCount = 0;

	/*
	 * Also clear the error context stack, to prevent error callbacks from
	 * being invoked by any elog/ereport calls made during proc_exit. Whatever
	 * context they might want to offer is probably not relevant, and in any
	 * case they are likely to fail outright after we've done things like
	 * aborting any open transaction.  (In normal exit scenarios the context
	 * stack should be empty anyway, but it might not be in the case of
	 * elog(FATAL) for example.)
	 */
	error_context_stack = NULL;
	/* For the same reason, reset debug_query_string before it's clobbered */
	debug_query_string = NULL;

	/* do our shared memory exits first */
	shmem_exit(code);

	elog(DEBUG3, "proc_exit(%d): %d callbacks to make",
		 code, on_proc_exit_index);

	/*
	 * call all the registered callbacks.
	 *
	 * Note that since we decrement on_proc_exit_index each time, if a
	 * callback calls ereport(ERROR) or ereport(FATAL) then it won't be
	 * invoked again when control comes back here (nor will the
	 * previously-completed callbacks).  So, an infinite loop should not be
	 * possible.
	 */
	while (--on_proc_exit_index >= 0)
		(*on_proc_exit_list[on_proc_exit_index].function) (code,
								  on_proc_exit_list[on_proc_exit_index].arg);

	on_proc_exit_index = 0;
}
Example #4
0
/*
 * Code shared between proc_exit and the atexit handler.  Note that in
 * normal exit through proc_exit, this will actually be called twice ...
 * but the second call will have nothing to do.
 */
void
proc_exit_prepare(int code)
{
	/*
	 * Once we set this flag, we are committed to exit.  Any ereport() will
	 * NOT send control back to the main loop, but right back here.
	 */
	proc_exit_inprogress = true;

	/*
	 * Forget any pending cancel or die requests; we're doing our best to
	 * close up shop already.  Note that the signal handlers will not set
	 * these flags again, now that proc_exit_inprogress is set.
	 */
	InterruptPending = false;
	ProcDiePending = false;
	QueryCancelPending = false;
	/* And let's just make *sure* we're not interrupted ... */
	ImmediateInterruptOK = false;
	InterruptWhenCallingPLUDF = false;
	InterruptHoldoffCount = 1;
	CritSectionCount = 0;

	/* do our shared memory exits first */
	shmem_exit(code);

	elog(DEBUG3, "proc_exit(%d): %d callbacks to make",
		 code, on_proc_exit_index);

	/*
	 * call all the registered callbacks.
	 *
	 * Note that since we decrement on_proc_exit_index each time, if a
	 * callback calls ereport(ERROR) or ereport(FATAL) then it won't be
	 * invoked again when control comes back here (nor will the
	 * previously-completed callbacks).  So, an infinite loop should not be
	 * possible.
	 */
	while (--on_proc_exit_index >= 0)
		(*on_proc_exit_list[on_proc_exit_index].function) (code,
								  on_proc_exit_list[on_proc_exit_index].arg);

	on_proc_exit_index = 0;
}
Example #5
0
int
main(int argc, char **argv)
{
	MyStorage  *storage;
	int			cpid;

	printf("Creating shared memory ... ");
	fflush(stdout);

	storage = (MyStorage *) PGSharedMemoryCreate(8192, false, 5433);

	storage->flag = 1234;

	printf("OK\n");

	printf("Creating semaphores ... ");
	fflush(stdout);

	PGReserveSemaphores(2, 5433);

	PGSemaphoreCreate(&storage->sem);

	printf("OK\n");

	/* sema initial value is 1, so lock should work */

	printf("Testing Lock ... ");
	fflush(stdout);

	PGSemaphoreLock(&storage->sem, false);

	printf("OK\n");

	/* now sema value is 0, so trylock should fail */

	printf("Testing TryLock ... ");
	fflush(stdout);

	if (PGSemaphoreTryLock(&storage->sem))
		printf("unexpected result!\n");
	else
		printf("OK\n");

	/* unlocking twice and then locking twice should work... */

	printf("Testing Multiple Lock ... ");
	fflush(stdout);

	PGSemaphoreUnlock(&storage->sem);
	PGSemaphoreUnlock(&storage->sem);

	PGSemaphoreLock(&storage->sem, false);
	PGSemaphoreLock(&storage->sem, false);

	printf("OK\n");

	/* check Reset too */

	printf("Testing Reset ... ");
	fflush(stdout);

	PGSemaphoreUnlock(&storage->sem);

	PGSemaphoreReset(&storage->sem);

	if (PGSemaphoreTryLock(&storage->sem))
		printf("unexpected result!\n");
	else
		printf("OK\n");

	/* Fork a child process and see if it can communicate */

	printf("Forking child process ... ");
	fflush(stdout);

	cpid = fork();
	if (cpid == 0)
	{
		/* In child */
		on_exit_reset();
		sleep(3);
		storage->flag++;
		PGSemaphoreUnlock(&storage->sem);
		proc_exit(0);
	}
	if (cpid < 0)
	{
		/* Fork failed */
		printf("failed: %s\n", strerror(errno));
		proc_exit(1);
	}

	printf("forked child pid %d OK\n", cpid);

	if (storage->flag != 1234)
		printf("Wrong value found in shared memory!\n");

	printf("Waiting for child (should wait 3 sec here) ... ");
	fflush(stdout);

	PGSemaphoreLock(&storage->sem, false);

	printf("OK\n");

	if (storage->flag != 1235)
		printf("Wrong value found in shared memory!\n");

	/* Test shutdown */

	printf("Running shmem_exit processing ... ");
	fflush(stdout);

	shmem_exit(0);

	printf("OK\n");

	printf("Tests complete.\n");

	proc_exit(0);

	return 0;					/* not reached */
}
Example #6
0
/*
 * Code shared between proc_exit and the atexit handler.  Note that in
 * normal exit through proc_exit, this will actually be called twice ...
 * but the second call will have nothing to do.
 */
void
proc_exit_prepare(int code)
{
	/*
	 * If we came here from any critical section, we don't have safe way to
	 * clean up shared memory or transaction state.  Though it's not a pleasant
	 * solution, this is better than messing up database.  This is the least
	 * desirable bail-out, and whenever you should see this situation, you
	 * should consider to resolve the actual programming error.
	 */
	if (CritSectionCount > 0 && !SuppressPanic)
		elog(PANIC, "process is dying from critical section");

	/*
	 * Once we set this flag, we are committed to exit.  Any ereport() will
	 * NOT send control back to the main loop, but right back here.
	 */
	proc_exit_inprogress = true;

	/*
	 * Forget any pending cancel or die requests; we're doing our best to
	 * close up shop already.  Note that the signal handlers will not set
	 * these flags again, now that proc_exit_inprogress is set.
	 */
	InterruptPending = false;
	ProcDiePending = false;
	QueryCancelPending = false;
	/* And let's just make *sure* we're not interrupted ... */
	ImmediateInterruptOK = false;
	InterruptWhenCallingPLUDF = false;
	InterruptHoldoffCount = 1;
	CritSectionCount = 0;

	/*
	 * Also clear the error context stack, to prevent error callbacks
	 * from being invoked by any elog/ereport calls made during proc_exit.
	 * Whatever context they might want to offer is probably not relevant,
	 * and in any case they are likely to fail outright after we've done
	 * things like aborting any open transaction.  (In normal exit scenarios
	 * the context stack should be empty anyway, but it might not be in the
	 * case of elog(FATAL) for example.)
	 */
	error_context_stack = NULL;

	/*
	* Make sure interconnect thread quit before shmem_exit() in FATAL case.
	* Otherwise, shmem_exit() may free MemoryContex of MotionConns in connHtab unexpectedly;
	*
	* For example: PORTAL_MULTI_QUERY strategy doesn't bind estate with portal,
	* so when fatal occurs, MotionConns of estate don't get removed through
	* TeardownInterconnect(), but MemoryContex of these MotionConns are freed.
	*
	* It's ok to shutdown Interconnect background thread here, process is dying, no
	* necessary to receive more motion data.
	*/
	WaitInterconnectQuit();

	/* do our shared memory exits first */
	shmem_exit(code);

	elog(DEBUG3, "proc_exit(%d): %d callbacks to make",
		 code, on_proc_exit_index);

	/*
	 * call all the registered callbacks.
	 *
	 * Note that since we decrement on_proc_exit_index each time, if a
	 * callback calls ereport(ERROR) or ereport(FATAL) then it won't be
	 * invoked again when control comes back here (nor will the
	 * previously-completed callbacks).  So, an infinite loop should not be
	 * possible.
	 */
	while (--on_proc_exit_index >= 0)
		(*on_proc_exit_list[on_proc_exit_index].function) (code,
								  on_proc_exit_list[on_proc_exit_index].arg);

	on_proc_exit_index = 0;
}