Beispiel #1
0
/* per-child process destroy function
 * Should be called only when the child process exits,
 * but SER continues running
 *
 * WARNING: this function call must be the very last action
 * before the child process exits, because the local config
 * is not available afterwards.
 */
void cfg_child_destroy(void)
{
	cfg_child_cb_t	*prev_cb;

	/* unref the local config */
	if (cfg_local) {
		CFG_UNREF(cfg_local);
		cfg_local = NULL;
	}

	if (!cfg_child_cb || cfg_child_cb==CFG_NO_CHILD_CBS) return;

	/* The lock must be held to make sure that the global config
	is not replaced meantime, and the other child processes do not
	leave the old value of *cfg_child_cb_last. Otherwise it could happen,
	that all the other processes move their own cfg_child_cb pointer before
	this process reaches *cfg_child_cb_last, though, it is very unlikely. */
	CFG_LOCK();

	/* go through the list and check whether there is any item that
	has to be freed (similar to cfg_update_local(), but without executing
	the callback functions) */
	while (cfg_child_cb != *cfg_child_cb_last) {
		prev_cb = cfg_child_cb;
		cfg_child_cb = cfg_child_cb->next;
		atomic_inc(&cfg_child_cb->refcnt);
		if (atomic_dec_and_test(&prev_cb->refcnt)) {
			/* No more pocess refers to this callback.
			Did this process block the deletion,
			or is there any other process that has not
			reached	prev_cb yet? */
			if (*cfg_child_cb_first == prev_cb) {
				/* yes, this process was blocking the deletion */
				*cfg_child_cb_first = cfg_child_cb;
				shm_free(prev_cb);
			}
		} else {
			/* no need to continue, because there is at least
			one process that stays exactly at the same point
			in the list, so it will free the items later */
			break;
		}
	}
	atomic_dec(&cfg_child_cb->refcnt);

	CFG_UNLOCK();
	cfg_child_cb = NULL;
}
Beispiel #2
0
/* installs a new global config
 *
 * replaced is an array of strings that must be freed together
 * with the previous global config.
 * cb_first and cb_last define a linked list of per-child process
 * callbacks. This list is added to the global linked list.
 */
void cfg_install_global(cfg_block_t *block, void **replaced,
			cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last)
{
	cfg_block_t* old_cfg;
	
	CFG_REF(block);

	if (replaced) {
		/* The replaced array is specified, it has to be linked to the child cb structure.
		 * The last child process processing this structure will free the old strings and the array. */
		if (cb_first) {
			cb_first->replaced = replaced;
		} else {
			/* At least one child cb structure is needed. */
			cb_first = cfg_child_cb_new(NULL, NULL, NULL, 0 /* gname, name, cb, type */);
			if (cb_first) {
				cb_last = cb_first;
				cb_first->replaced = replaced;
			} else {
				LOG(L_ERR, "ERROR: cfg_install_global(): not enough shm memory\n");
				/* Nothing more can be done here, the replaced strings are still needed,
				 * they cannot be freed at this moment.
				 */
			}
		}
	}

	CFG_LOCK();

	old_cfg = *cfg_global;
	*cfg_global = block;

	if (cb_first)
		cfg_install_child_cb(cb_first, cb_last);

	CFG_UNLOCK();
	
	if (old_cfg)
		CFG_UNREF(old_cfg);
}
Beispiel #3
0
/* Reset the local configuration of the main process back to its original state
 * to make sure that the forked processes are not affected.
 */
void cfg_main_reset_local(void)
{
	cfg_group_t	*group;

	/* Unref the local config, and set it back to NULL.
	 * Each child will set its own local configuration. */
	if (cfg_local) {
		CFG_UNREF(cfg_local);
		cfg_local = NULL;

		/* restore the original value of the module handles */
		for (	group = cfg_group;
			group;
			group = group->next
		)
			*(group->handle) = group->orig_handle;
		/* The handle might have pointed to a group instance,
		 * reset the instance counter. */
		cfg_ginst_count = 0;
	}
	cfg_child_cb = NULL;
}
Beispiel #4
0
/* installs a new global config
 *
 * replaced is an array of strings that must be freed together
 * with the previous global config.
 * cb_first and cb_last define a linked list of per-child process
 * callbacks. This list is added to the global linked list.
 */
void cfg_install_global(cfg_block_t *block, char **replaced,
			cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last)
{
	cfg_block_t* old_cfg;
	
	CFG_REF(block);

	CFG_LOCK();

	old_cfg = *cfg_global;
	*cfg_global = block;

	if (cb_first)
		cfg_install_child_cb(cb_first, cb_last);

	CFG_UNLOCK();
	
	if (old_cfg) {
		if (replaced) (old_cfg)->replaced = replaced;
		CFG_UNREF(old_cfg);
	}

}