Esempio n. 1
0
cs_error_t sam_register (
	unsigned int *instance_id)
{
	cs_error_t error;
	pid_t pid;
	int pipe_error;
	int pipe_fd[2];
	enum sam_parent_action_t action;
	int child_status;

	if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_INITIALIZED) {
		return (CS_ERR_BAD_HANDLE);
	}

	error = CS_OK;

	while (1) {
		pipe_error = pipe (pipe_fd);

		if (pipe_error != 0) {
			/*
			 *  Pipe creation error
			 */
			error = CS_ERR_LIBRARY;
			goto error_exit;
		}

		sam_internal_data.instance_id++;

		sam_internal_data.term_send = 0;

		pid = fork ();

		if (pid == -1) {
			/*
			 *  Fork error
			 */
			sam_internal_data.instance_id--;

			error = CS_ERR_LIBRARY;
			goto error_exit;
		}

		if (pid == 0) {
			/*
			 *  Child process
			 */
			close (pipe_fd[0]);

			sam_internal_data.parent_fd = pipe_fd[1];
			if (instance_id)
				*instance_id = sam_internal_data.instance_id;

			sam_internal_data.internal_status = SAM_INTERNAL_STATUS_REGISTERED;

			goto error_exit;
		} else {
			/*
			 *  Parent process
			 */
			close (pipe_fd[1]);

			action = sam_parent_handler (pipe_fd[0], pid);

			close (pipe_fd[0]);

			if (action == SAM_PARENT_ACTION_ERROR) {
				error = CS_ERR_LIBRARY;
				goto error_exit;
			}

			/*
			 * We really don't like zombies
			 */
			while (waitpid (pid, &child_status, 0) == -1 && errno == EINTR)
				;

			if (action == SAM_PARENT_ACTION_RECOVERY) {
				if (sam_internal_data.recovery_policy == SAM_RECOVERY_POLICY_QUIT)
					action = SAM_PARENT_ACTION_QUIT;
			}

			if (action == SAM_PARENT_ACTION_QUIT) {
				exit (WEXITSTATUS (child_status));
			}

		}
	}

error_exit:
	return (error);
}
Esempio n. 2
0
cs_error_t sam_register (
	unsigned int *instance_id)
{
	cs_error_t error;
	pid_t pid;
	int pipe_error;
	int pipe_fd_out[2], pipe_fd_in[2];
	enum sam_parent_action_t action, old_action;
	int child_status;
	sam_recovery_policy_t recpol;

	if (sam_internal_data.internal_status != SAM_INTERNAL_STATUS_INITIALIZED) {
		return (CS_ERR_BAD_HANDLE);
	}

	recpol = sam_internal_data.recovery_policy;

	if (recpol & SAM_RECOVERY_POLICY_CONFDB) {
		/*
		 * Register to objdb
		 */
		if ((error = sam_confdb_register ()) != CS_OK) {
			goto error_exit;
		}
	}

	error = CS_OK;

	while (1) {
		if ((pipe_error = pipe (pipe_fd_out)) != 0) {
			error = CS_ERR_LIBRARY;
			goto error_exit;
		}

		if ((pipe_error = pipe (pipe_fd_in)) != 0) {
			close (pipe_fd_out[0]);
			close (pipe_fd_out[1]);

			error = CS_ERR_LIBRARY;
			goto error_exit;
		}

		if (recpol & SAM_RECOVERY_POLICY_CONFDB) {
			if ((error = sam_confdb_update_key (SAM_CONFDB_KEY_STATE, SAM_CONFDB_S_REGISTERED)) != CS_OK) {
				goto error_exit;
			}
		}

		sam_internal_data.instance_id++;

		sam_internal_data.term_send = 0;

		pid = fork ();

		if (pid == -1) {
			/*
			 *  Fork error
			 */
			sam_internal_data.instance_id--;

			error = CS_ERR_LIBRARY;
			goto error_exit;
		}

		if (pid == 0) {
			/*
			 *  Child process
			 */
			close (pipe_fd_out[0]);
			close (pipe_fd_in[1]);

			sam_internal_data.child_fd_out = pipe_fd_out[1];
			sam_internal_data.child_fd_in = pipe_fd_in[0];

			if (instance_id)
				*instance_id = sam_internal_data.instance_id;

			sam_internal_data.am_i_child = 1;
			sam_internal_data.internal_status = SAM_INTERNAL_STATUS_REGISTERED;

			pthread_mutex_init (&sam_internal_data.lock, NULL);

			goto error_exit;
		} else {
			/*
			 *  Parent process
			 */
			close (pipe_fd_out[1]);
			close (pipe_fd_in[0]);

			action = sam_parent_handler (pipe_fd_out[0], pipe_fd_in[1], pid);

			close (pipe_fd_out[0]);
			close (pipe_fd_in[1]);

			if (action == SAM_PARENT_ACTION_ERROR) {
				error = CS_ERR_LIBRARY;
				goto error_exit;
			}

			/*
			 * We really don't like zombies
			 */
			while (waitpid (pid, &child_status, 0) == -1 && errno == EINTR)
				;

			old_action = action;

			if (action == SAM_PARENT_ACTION_RECOVERY) {
				if (SAM_RP_MASK (sam_internal_data.recovery_policy) == SAM_RECOVERY_POLICY_QUIT)
					action = SAM_PARENT_ACTION_QUIT;
			}


			if (action == SAM_PARENT_ACTION_QUIT) {
				if (recpol & SAM_RECOVERY_POLICY_QUORUM) {
					quorum_finalize (sam_internal_data.quorum_handle);
				}

				if (recpol & SAM_RECOVERY_POLICY_CONFDB) {
					if (old_action == SAM_PARENT_ACTION_RECOVERY) {
						/*
						 * Mark as failed
						 */
						sam_confdb_update_key (SAM_CONFDB_KEY_STATE, SAM_CONFDB_S_FAILED);
					} else {
						sam_confdb_destroy_pid_obj ();
					}
				}

				exit (WEXITSTATUS (child_status));
			}


		}
	}

error_exit:
	return (error);
}