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); }
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); }