static void updproc_stop(boolean_t exit) { int4 status; int fclose_res; call_on_signal = NULL; /* Don't reenter on error */ if (pool_init) { rel_lock(jnlpool.jnlpool_dummy_reg); /* nullify jnlpool_ctl before detaching from jnlpool since if it is the other way, we might be interrupted * by the periodic timer routines and end up in jnl_write_epoch_rec() routine that dereferences jnlpool_ctl * since it is non-NULL although it has been detached from and is no longer valid memory. */ jnlpool_ctl = NULL; #ifdef UNIX mutex_cleanup(jnlpool.jnlpool_dummy_reg); SHMDT(jnlpool.jnlpool_ctl); #elif defined(VMS) if (SS$_NORMAL != (status = detach_shm(jnlpool.shm_range))) repl_log(stderr, TRUE, TRUE, "Error detaching from jnlpool : %s\n", REPL_STR_ERROR); if (SS$_NORMAL != (status = signoff_from_gsec(jnlpool.shm_lockid))) repl_log(stderr, TRUE, TRUE, "Error dequeueing lock on jnlpool global section : %s\n", REPL_STR_ERROR); #else #error Unsupported Platform #endif jnlpool.jnlpool_ctl = NULL; pool_init = FALSE; } recvpool.upd_proc_local->upd_proc_shutdown = NORMAL_SHUTDOWN; recvpool.upd_proc_local->upd_proc_pid = 0; #ifdef UNIX SHMDT(recvpool.recvpool_ctl); #elif defined(VMS) if(SS$_NORMAL != (status = detach_shm(recvpool.shm_range))) repl_log(stderr, TRUE, TRUE, "Update process could not detach from recvpool : %s\n", REPL_STR_ERROR); if (SS$_NORMAL != (status = signoff_from_gsec(recvpool.shm_lockid))) repl_log(stderr, TRUE, TRUE, "Error dequeueing lock on recvpool global section : %s\n", REPL_STR_ERROR); #else #error Unsupported Platform #endif recvpool.recvpool_ctl = NULL; gtm_event_log_close(); if (exit) mupip_exit(SS_NORMAL); return; }
void mupip_exit_handler(void) { char err_log[1024]; FILE *fp; boolean_t files_closed = TRUE; if (exit_handler_active) /* Don't recurse if exit handler exited */ return; exit_handler_active = TRUE; SET_PROCESS_EXITING_TRUE; if (jgbl.mupip_journal) { files_closed = mur_close_files(); mupip_jnl_recover = FALSE; } jgbl.dont_reset_gbl_jrec_time = jgbl.forw_phase_recovery = FALSE; CANCEL_TIMERS; /* Cancel all unsafe timers - No unpleasant surprises */ secshr_db_clnup(NORMAL_TERMINATION); if (dollar_tlevel) OP_TROLLBACK(0); if (is_updhelper && NULL != helper_entry) /* haven't had a chance to cleanup, must be an abnormal exit */ { helper_entry->helper_shutdown = ABNORMAL_SHUTDOWN; helper_entry->helper_pid = 0; /* vacate my slot */ helper_entry = NULL; } if (recvpool.recvpool_ctl) { SHMDT(recvpool.recvpool_ctl); recvpool.recvpool_ctl = NULL; } gv_rundown(); /* also takes care of detaching from the journal pool */ relinkctl_rundown(TRUE, TRUE); /* decrement relinkctl-attach & rtnobj-reference counts */ /* Log the exit of replication servers. In case they are exiting abnormally, their log file pointers * might not be set up. In that case, use "stderr" for logging. */ if (is_src_server) { fp = (NULL != gtmsource_log_fp) ? gtmsource_log_fp : stderr; repl_log(fp, TRUE, TRUE, "Source server exiting...\n\n"); } else if (is_rcvr_server) { fp = (NULL != gtmrecv_log_fp) ? gtmrecv_log_fp : stderr; repl_log(fp, TRUE, TRUE, "Receiver server exiting...\n\n"); } else if (is_updproc) { fp = (NULL != updproc_log_fp) ? updproc_log_fp : stderr; repl_log(fp, TRUE, TRUE, "Update process exiting...\n\n"); } else if (is_updhelper) { fp = (NULL != updhelper_log_fp) ? updhelper_log_fp : stderr; repl_log(fp, TRUE, TRUE, "Helper exiting...\n\n"); } else mu_reset_term_characterstics(); /* the replication servers use files for output/error, not terminal */ flush_pio(); util_out_close(); close_repl_logfiles(); print_exit_stats(); io_rundown(RUNDOWN_EXCEPT_STD); GTMCRYPT_CLOSE; if (need_core && !created_core) { ++core_in_progress; DUMP_CORE; /* This will not return */ } if (!files_closed) _exit(EXIT_FAILURE); }
int gtmsource_ipc_cleanup(boolean_t auto_shutdown, int *exit_status) { boolean_t i_am_the_last_user, attempt_ipc_cleanup; int status, detach_status, remove_status, expected_nattach; unix_db_info *udi; struct shmid_ds shm_buf; /* Attempt cleaning up the IPCs */ attempt_ipc_cleanup = TRUE; /* Wait for the Source Server to detach and takeover the semaphore */ if (!auto_shutdown && 0 > grab_sem(SOURCE, SRC_SERV_COUNT_SEM)) { repl_log(stderr, FALSE, TRUE, "Error taking control of source server count semaphore : %s. Shutdown not complete\n", REPL_SEM_ERROR); *exit_status = ABNORMAL_SHUTDOWN; attempt_ipc_cleanup = FALSE; } udi = (unix_db_info *)FILE_INFO(jnlpool.jnlpool_dummy_reg); if (!auto_shutdown || !gtmsource_srv_count) expected_nattach = 1; /* Self, or parent */ else expected_nattach = 0; /* Source server already detached */ i_am_the_last_user = (((status = shmctl(udi->shmid, IPC_STAT, &shm_buf)) == 0) && (shm_buf.shm_nattch == expected_nattach)); if (!i_am_the_last_user) { if (status < 0) repl_log(stderr, FALSE, TRUE, "Error in jnlpool shmctl : %s\n", STRERROR(ERRNO)); else repl_log(stderr, FALSE, TRUE, "Not deleting jnlpool ipcs. %d processes still attached to jnlpool\n", shm_buf.shm_nattch - expected_nattach); attempt_ipc_cleanup = FALSE; *exit_status = ABNORMAL_SHUTDOWN; } if (attempt_ipc_cleanup) { if (INVALID_SHMID != udi->shmid && (auto_shutdown || (detach_status = SHMDT(jnlpool.jnlpool_ctl)) == 0) && (remove_status = shm_rmid(udi->shmid)) == 0) { jnlpool.jnlpool_ctl = jnlpool_ctl = NULL; pool_init = FALSE; repl_log(stdout, FALSE, FALSE, "Journal pool shared memory removed\n"); if (0 == (status = remove_sem_set(SOURCE))) repl_log(stdout, FALSE, TRUE, "Journal pool semaphore removed\n"); else { repl_log(stderr, FALSE, TRUE, "Error removing jnlpool semaphore : %s\n", STRERROR(status)); *exit_status = ABNORMAL_SHUTDOWN; } } else if (INVALID_SHMID != udi->shmid) { if (!auto_shutdown && detach_status < 0) repl_log(stderr, FALSE, FALSE, "Error detaching from jnlpool shared memory : %s. Shared memory not removed\n", STRERROR(ERRNO)); else if (remove_status != 0) { if (!auto_shutdown) { jnlpool.jnlpool_ctl = NULL; /* Detached successfully */ jnlpool_ctl = NULL; pool_init = FALSE; } repl_log(stderr, FALSE, TRUE, "Error removing jnlpool shared memory : %s\n", STRERROR(ERRNO)); } *exit_status = ABNORMAL_SHUTDOWN; } } return attempt_ipc_cleanup; }
int gtmrecv_end1(boolean_t auto_shutdown) { int4 strm_idx; int exit_status, idx, status, save_errno; int fclose_res, rc; seq_num log_seqno, log_seqno1, jnlpool_seqno, jnlpool_strm_seqno[MAX_SUPPL_STRMS]; uint4 savepid; exit_status = gtmrecv_end_helpers(TRUE); exit_status = gtmrecv_endupd(); log_seqno = recvpool.recvpool_ctl->jnl_seqno; log_seqno1 = recvpool.upd_proc_local->read_jnl_seqno; strm_idx = recvpool.gtmrecv_local->strm_index; /* Detach from receive pool */ recvpool.gtmrecv_local->shutdown = exit_status; recvpool.gtmrecv_local->recv_serv_pid = 0; if (0 > SHMDT(recvpool.recvpool_ctl)) repl_log(stderr, TRUE, TRUE, "Error detaching from Receive Pool : %s\n", REPL_STR_ERROR); recvpool.recvpool_ctl = NULL; assert((NULL != jnlpool_ctl) && (jnlpool_ctl == jnlpool.jnlpool_ctl)); if (NULL != jnlpool.jnlpool_ctl) { /* Reset fields that might have been initialized by the receiver server after connecting to the primary. * It is ok not to hold the journal pool lock while updating jnlpool_ctl fields since this will be the * only process updating those fields. */ jnlpool.jnlpool_ctl->primary_instname[0] = '\0'; jnlpool.jnlpool_ctl->gtmrecv_pid = 0; jnlpool_seqno = jnlpool.jnlpool_ctl->jnl_seqno; for (idx = 0; idx < MAX_SUPPL_STRMS; idx++) jnlpool_strm_seqno[idx] = jnlpool.jnlpool_ctl->strm_seqno[idx]; /* Also take this opportunity to detach from the journal pool except in the auto_shutdown case. This is because * the fields "jnlpool_ctl->repl_inst_filehdr->recvpool_semid" and "jnlpool_ctl->repl_inst_filehdr->recvpool_shmid" * need to be reset by "gtmrecv_jnlpool_reset" (called from "gtmrecv_shutdown") which is invoked a little later. */ if (!auto_shutdown) { JNLPOOL_SHMDT(status, save_errno); if (0 > status) repl_log(stderr, TRUE, TRUE, "Error detaching from Journal Pool : %s\n", STRERROR(save_errno)); jnlpool.jnlpool_ctl = jnlpool_ctl = NULL; jnlpool.repl_inst_filehdr = NULL; jnlpool.gtmsrc_lcl_array = NULL; jnlpool.gtmsource_local_array = NULL; jnlpool.jnldata_base = NULL; pool_init = FALSE; } } else jnlpool_seqno = 0; gtmrecv_free_msgbuff(); gtmrecv_free_filter_buff(); recvpool.recvpool_ctl = NULL; /* Close the connection with the Receiver */ if (FD_INVALID != gtmrecv_listen_sock_fd) CLOSEFILE_RESET(gtmrecv_listen_sock_fd, rc); /* resets "gtmrecv_listen_sock_fd" to FD_INVALID */ if (FD_INVALID != gtmrecv_sock_fd) CLOSEFILE_RESET(gtmrecv_sock_fd, rc); /* resets "gtmrecv_sock_fd" to FD_INVALID */ repl_log(gtmrecv_log_fp, TRUE, FALSE, "REPL INFO - Current Jnlpool Seqno : %llu\n", jnlpool_seqno); for (idx = 0; idx < MAX_SUPPL_STRMS; idx++) { if (jnlpool_strm_seqno[idx]) repl_log(gtmrecv_log_fp, TRUE, FALSE, "REPL INFO - Stream # %d : Current Jnlpool Stream Seqno : %llu\n", idx, jnlpool_strm_seqno[idx]); } if (0 < strm_idx) repl_log(gtmrecv_log_fp, TRUE, FALSE, "REPL INFO - Receiver server has Stream # %d\n", strm_idx); repl_log(gtmrecv_log_fp, TRUE, TRUE, "REPL INFO - Current Update process Read Seqno : %llu\n", log_seqno1); repl_log(gtmrecv_log_fp, TRUE, TRUE, "REPL INFO - Current Receive Pool Seqno : %llu\n", log_seqno); /* If log_seqno/log_seqno1 is 0, then do not decrement it as that will be interpreted as a huge positive seqno. Keep it 0 */ if (log_seqno) log_seqno--; if (log_seqno1) log_seqno1--; repl_log(gtmrecv_log_fp, TRUE, FALSE, "REPL INFO - Last Recvd Seqno : %llu Jnl Total : %llu Msg Total : %llu\n", log_seqno, repl_recv_data_processed, repl_recv_data_recvd); repl_log(gtmrecv_log_fp, TRUE, TRUE, "REPL INFO - Last Seqno processed by update process : %llu\n", log_seqno1); gtm_event_log_close(); if (gtmrecv_filter & EXTERNAL_FILTER) repl_stop_filter(); if (auto_shutdown) return (exit_status); else gtmrecv_exit(exit_status - NORMAL_SHUTDOWN); return -1; /* This will never get executed, added to make compiler happy */ }
int gtmrecv_ipc_cleanup(boolean_t auto_shutdown, int *exit_status) { boolean_t i_am_the_last_user, attempt_ipc_cleanup; int status, detach_status, remove_status, expected_nattach; struct shmid_ds shm_buf; /* Attempt cleaning up the IPCs */ attempt_ipc_cleanup = TRUE; /* * Wait for the Receiver Server and Update Process to detach and * takeover the semaphores. Note that the Receiver Server has already * waited for the Update Process to detach. It is done here as a * precaution against Receiver Server crashes. */ if (!auto_shutdown) status = grab_sem(RECV, RECV_SERV_COUNT_SEM); else status = 0; if (0 == status && 0 > (status = grab_sem(RECV, UPD_PROC_COUNT_SEM))) rel_sem(RECV, RECV_SERV_COUNT_SEM); if (status < 0) { repl_log(stderr, FALSE, TRUE, "Error taking control of Receiver Server/Update Process count semaphore : %s. Shutdown not complete\n", REPL_SEM_ERROR); *exit_status = ABNORMAL_SHUTDOWN; attempt_ipc_cleanup = FALSE; } /* Now we have locked out all users from the receive pool */ if (!auto_shutdown || !gtmrecv_srv_count) expected_nattach = 1; /* Self, or parent */ else expected_nattach = 0; /* Receiver server already detached */ i_am_the_last_user = (((status = shmctl(recvpool_shmid, IPC_STAT, &shm_buf)) == 0) && (shm_buf.shm_nattch == expected_nattach)); if (!i_am_the_last_user) { if (status < 0) repl_log(stderr, FALSE, TRUE, "Error in jnlpool shmctl : %s\n", STRERROR(ERRNO)); else repl_log(stderr, FALSE, TRUE, "Not deleting receive pool ipcs. %d processes still attached to receive pool\n", shm_buf.shm_nattch - expected_nattach); attempt_ipc_cleanup = FALSE; *exit_status = ABNORMAL_SHUTDOWN; } if (attempt_ipc_cleanup) { if (INVALID_SHMID != recvpool_shmid && (auto_shutdown || (detach_status = SHMDT(recvpool.recvpool_ctl)) == 0) && (remove_status = shm_rmid(recvpool_shmid)) == 0) { recvpool.recvpool_ctl = NULL; repl_log(stdout, FALSE, FALSE, "Receive pool shared memory removed\n"); if (0 == (status = remove_sem_set(RECV))) repl_log(stdout, FALSE, TRUE, "Receive pool semaphore removed\n"); else { repl_log(stderr, FALSE, TRUE, "Error removing receive pool semaphore : %s\n", STRERROR(status)); *exit_status = ABNORMAL_SHUTDOWN; } } else if (INVALID_SHMID != recvpool_shmid) { if (!auto_shutdown && detach_status < 0) repl_log(stderr, FALSE, FALSE, "Error detaching from receive pool shared memory : %s. Shared memory not removed\n", STRERROR(ERRNO)); else if (remove_status != 0) { if (!auto_shutdown) recvpool.recvpool_ctl = NULL; /* Detached successfully */ repl_log(stderr, FALSE, TRUE, "Error removing receive pool shared memory : %s\n", STRERROR(ERRNO)); } *exit_status = ABNORMAL_SHUTDOWN; } } return attempt_ipc_cleanup; }