/**************************************************************************** Name : ncs_eda_startup Description : This routine creates a EDSv agent infrastructure to interface with EDSv service. Once the infrastructure is created from then on use_count is incremented for every startup request. Arguments : - NIL- Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE Notes : None ******************************************************************************/ unsigned int ncs_eda_startup(void) { NCS_LIB_REQ_INFO lib_create; TRACE_ENTER(); osaf_mutex_lock_ordie(&s_agent_startup_mutex); if (eda_use_count > 0) { /* Already created, so just increment the use_count */ eda_use_count++; osaf_mutex_unlock_ordie(&s_agent_startup_mutex); TRACE_LEAVE2("Library use count: %u", eda_use_count); return NCSCC_RC_SUCCESS; } /*** Init EDA ***/ memset(&lib_create, 0, sizeof(lib_create)); lib_create.i_op = NCS_LIB_REQ_CREATE; if (ncs_eda_lib_req(&lib_create) != NCSCC_RC_SUCCESS) { osaf_mutex_unlock_ordie(&s_agent_startup_mutex); return NCSCC_RC_FAILURE; } else { eda_use_count = 1; TRACE("EDA agent library initialized"); } osaf_mutex_unlock_ordie(&s_agent_startup_mutex); TRACE_LEAVE2("Library use count: %u", eda_use_count); return NCSCC_RC_SUCCESS; }
/**************************************************************************** Name : ncs_mqa_startup Description : This routine creates a MQSv agent infrastructure to interface with MQSv service. Once the infrastructure is created from then on use_count is incremented for every startup request. Arguments : - NIL- Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE Notes : None ******************************************************************************/ unsigned int ncs_mqa_startup(void) { NCS_LIB_REQ_INFO lib_create; char *value = NULL; osaf_mutex_lock_ordie(&s_agent_startup_mutex); if (mqa_use_count > 0) { /* Already created, so just increment the use_count */ mqa_use_count++; osaf_mutex_unlock_ordie(&s_agent_startup_mutex); return NCSCC_RC_SUCCESS; } /*** Init MQA ***/ memset(&lib_create, 0, sizeof(lib_create)); lib_create.i_op = NCS_LIB_REQ_CREATE; if (mqa_lib_req(&lib_create) != NCSCC_RC_SUCCESS) { osaf_mutex_unlock_ordie(&s_agent_startup_mutex); return m_LEAP_DBG_SINK(NCSCC_RC_FAILURE); } else { printf("\nMQSV:MQA:ON"); mqa_use_count = 1; } /* Initialize trace system first of all so we can see what is going. */ if ((value = getenv("MQA_TRACE_PATHNAME")) != NULL) { logtrace_init("mqa", value, CATEGORY_ALL); } osaf_mutex_unlock_ordie(&s_agent_startup_mutex); return NCSCC_RC_SUCCESS; }
uint32_t ncsmds_adm_api(NCSMDS_ADMOP_INFO *mds_adm) { uint32_t status = NCSCC_RC_SUCCESS; if (mds_adm == NULL) { m_MDS_LOG_ERR("MDS_PAPI : Invalid Input mds_adm = NULL in ncsmds_adm_api()"); return NCSCC_RC_FAILURE; } osaf_mutex_lock_ordie(&gl_mds_library_mutex); if (gl_mds_mcm_cb == NULL) { m_MDS_LOG_ERR("MDS_PAPI : ncsmds_adm_api() : MDS is not initialized gl_mds_mcm_cb = NULL "); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return NCSCC_RC_FAILURE; } switch (mds_adm->i_op) { case MDS_ADMOP_VDEST_CREATE: status = mds_mcm_vdest_create(mds_adm); break; case MDS_ADMOP_VDEST_CONFIG: status = mds_mcm_vdest_chg_role(mds_adm); break; case MDS_ADMOP_VDEST_DESTROY: status = mds_mcm_vdest_destroy(mds_adm); break; case MDS_ADMOP_VDEST_QUERY: status = mds_mcm_vdest_query(mds_adm); break; case MDS_ADMOP_PWE_CREATE: status = mds_mcm_pwe_create(mds_adm); break; case MDS_ADMOP_PWE_DESTROY: status = mds_mcm_pwe_destroy(mds_adm); break; case MDS_ADMOP_PWE_QUERY: status = mds_mcm_adm_pwe_query(mds_adm); break; default: m_MDS_LOG_ERR("MDS_PAPI : API Option Unsupported in ncsmds_adm_api()"); status = NCSCC_RC_FAILURE; break; } osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return status; }
FILE *ncs_os_fopen(const char *fpath, const char *fmode) { FILE *fp = NULL; int flags = 0; osaf_mutex_lock_ordie(&s_cloexec_mutex); fp = fopen(fpath, fmode); if (fp == NULL) { osaf_mutex_unlock_ordie(&s_cloexec_mutex); return NULL; } flags = fcntl(fileno(fp), F_GETFD, 0); fcntl(fileno(fp), F_SETFD, (flags | FD_CLOEXEC)); osaf_mutex_unlock_ordie(&s_cloexec_mutex); return fp; }
uint32_t ncs_sel_obj_create(NCS_SEL_OBJ *o_sel_obj) { int s_pair[2]; int flags = 0; osaf_mutex_lock_ordie(&s_cloexec_mutex); if (0 != socketpair(AF_UNIX, SOCK_STREAM, 0, s_pair)) { syslog(LOG_ERR, "%s: socketpair failed - %s", __FUNCTION__, strerror(errno)); osaf_mutex_unlock_ordie(&s_cloexec_mutex); return NCSCC_RC_FAILURE; } flags = fcntl(s_pair[0], F_GETFD, 0); fcntl(s_pair[0], F_SETFD, (flags | FD_CLOEXEC)); flags = fcntl(s_pair[1], F_GETFD, 0); fcntl(s_pair[1], F_SETFD, (flags | FD_CLOEXEC)); osaf_mutex_unlock_ordie(&s_cloexec_mutex); if (s_pair[0] > s_pair[1]) { /* Ensure s_pair[1] is equal or greater */ int temp = s_pair[0]; s_pair[0] = s_pair[1]; s_pair[1] = temp; } o_sel_obj->raise_obj = s_pair[0]; o_sel_obj->rmv_obj = s_pair[1]; /* Raising indications should be a non-blocking operation. Otherwise, it can lead to deadlocks among reader and writer applications. */ flags = fcntl(o_sel_obj->raise_obj, F_GETFL, 0); if (fcntl(o_sel_obj->raise_obj, F_SETFL, (flags | O_NONBLOCK)) == -1) { syslog(LOG_ERR, "%s: fcntl failed - %s", __FUNCTION__, strerror(errno)); (void) ncs_sel_obj_destroy(*o_sel_obj); return NCSCC_RC_FAILURE; } return NCSCC_RC_SUCCESS; }
/*************************************************************************** * * unsigned int * ncs_os_lock( NCS_OS_LOCK *, NCS_OS_LOCK_REQUEST ) * * Description: * This routine handles all operating system lock primitives. * * Synopsis: * * Call Arguments: * lock ............... pointer to a NCS_OS_LOCK * request ............... action request * * Returns: * Returns NCSCC_RC_SUCCESS if successful, otherwise NCSCC_RC_FAILURE. * * Notes: * ****************************************************************************/ unsigned int ncs_os_lock(NCS_OS_LOCK * lock, NCS_OS_LOCK_REQUEST request, unsigned int type) { switch (request) { case NCS_OS_LOCK_CREATE: { pthread_mutexattr_t mutex_attr; if (pthread_mutexattr_init(&mutex_attr) != 0) return (NCSCC_RC_FAILURE); if (pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE) != 0) return (NCSCC_RC_FAILURE); if (pthread_mutex_init(&lock->lock, &mutex_attr) != 0) { pthread_mutexattr_destroy(&mutex_attr); return (NCSCC_RC_FAILURE); } if (pthread_mutexattr_destroy(&mutex_attr) != 0) return (NCSCC_RC_FAILURE); break; } case NCS_OS_LOCK_RELEASE: if (pthread_mutex_destroy(&lock->lock) != 0) return (NCSCC_RC_FAILURE); break; case NCS_OS_LOCK_LOCK: osaf_mutex_lock_ordie(&lock->lock); break; case NCS_OS_LOCK_UNLOCK: osaf_mutex_unlock_ordie(&lock->lock); break; default: return (NCSCC_RC_FAILURE); } return NCSCC_RC_SUCCESS; }
/**************************************************************************** Name : ncs_cpa_shutdown Description : This routine destroys the CPSv agent infrastructure created to interface CPSv service. If the registered users are > 1, it just decrements the use_count. Arguments : - NIL - Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE Notes : None ******************************************************************************/ unsigned int ncs_cpa_shutdown(void) { uint32_t rc = NCSCC_RC_SUCCESS; osaf_mutex_lock_ordie(&s_agent_startup_mutex); if (cpa_use_count > 1) { /* Still users extis, so just decrement the use_count */ cpa_use_count--; } else if (cpa_use_count == 1) { NCS_LIB_REQ_INFO lib_destroy; memset(&lib_destroy, 0, sizeof(lib_destroy)); lib_destroy.i_op = NCS_LIB_REQ_DESTROY; rc = cpa_lib_req(&lib_destroy); cpa_use_count = 0; } osaf_mutex_unlock_ordie(&s_agent_startup_mutex); return rc; }
/**************************************************************************** Name : ncs_eda_shutdown Description : This routine destroys the EDSv agent infrastructure created to interface EDSv service. If the registered users are > 1, it just decrements the use_count. Arguments : - NIL - Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE Notes : None ******************************************************************************/ unsigned int ncs_eda_shutdown(void) { uint32_t rc = NCSCC_RC_SUCCESS; TRACE_ENTER(); osaf_mutex_lock_ordie(&s_agent_startup_mutex); if (eda_use_count > 1) { /* Still users extis, so just decrement the use_count */ eda_use_count--; } else if (eda_use_count == 1) { NCS_LIB_REQ_INFO lib_destroy; memset(&lib_destroy, 0, sizeof(lib_destroy)); lib_destroy.i_op = NCS_LIB_REQ_DESTROY; rc = ncs_eda_lib_req(&lib_destroy); eda_use_count = 0; } osaf_mutex_unlock_ordie(&s_agent_startup_mutex); TRACE_LEAVE2("Library use count: %u", eda_use_count); return rc; }
uint32_t ncsmds_api(NCSMDS_INFO *svc_to_mds_info) { uint32_t status = NCSCC_RC_SUCCESS; if (svc_to_mds_info == NULL) { m_MDS_LOG_ERR("MDS_PAPI : Input svc_to_mds_info = NULL in ncsmds_api()"); return NCSCC_RC_FAILURE; } osaf_mutex_lock_ordie(&gl_mds_library_mutex); if (gl_mds_mcm_cb == NULL) { m_MDS_LOG_ERR("MDS_PAPI : ncsmds_api() : MDS is not initialized gl_mds_mcm_cb = NULL "); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return NCSCC_RC_FAILURE; } /* Vailidate pwe hdl */ if (svc_to_mds_info->i_op == MDS_SEND || svc_to_mds_info->i_op == MDS_DIRECT_SEND) { /* Don't validate pwe hdl */ } else { status = mds_validate_pwe_hdl((MDS_PWE_HDL)svc_to_mds_info->i_mds_hdl); if (status == NCSCC_RC_FAILURE) { m_MDS_LOG_ERR("MDS_PAPI : Invalid pwe hdl in ncsmds_api()"); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return NCSCC_RC_FAILURE; } } switch (svc_to_mds_info->i_op) { case MDS_INSTALL: status = mds_mcm_svc_install(svc_to_mds_info); break; case MDS_UNINSTALL: status = mds_mcm_svc_uninstall(svc_to_mds_info); break; case MDS_SUBSCRIBE: case MDS_RED_SUBSCRIBE: status = mds_mcm_svc_subscribe(svc_to_mds_info); break; case MDS_CANCEL: status = mds_mcm_svc_unsubscribe(svc_to_mds_info); break; /* case MDS_SYS_SUBSCRIBE: status = mds_sys_subscribe(svc_to_mds_info); break; */ case MDS_SEND: case MDS_DIRECT_SEND: status = mds_send(svc_to_mds_info); break; case MDS_RETRIEVE: status = mds_retrieve(svc_to_mds_info); break; case MDS_QUERY_DEST: status = mds_mcm_dest_query(svc_to_mds_info); break; case MDS_QUERY_PWE: status = mds_mcm_pwe_query(svc_to_mds_info); break; case MDS_NODE_SUBSCRIBE: status = mds_mcm_node_subscribe(svc_to_mds_info); break; case MDS_NODE_UNSUBSCRIBE: status = mds_mcm_node_unsubscribe(svc_to_mds_info); break; default: m_MDS_LOG_ERR("MDS_PAPI : API Option Unsupported in ncsmds_api()"); status = NCSCC_RC_FAILURE; break; } osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return status; }
/** * Write a log record to file * The file must be opened for append * * @param indata[in] Type wlrh_t * @param outdata[out], int errno, 0 if no error * @param max_outsize[in], always sizeof(int) * @return (-1) on error or number of written bytes */ int write_log_record_hdl(void *indata, void *outdata, size_t max_outsize, bool *timeout_f) { int rc, bytes_written = 0; off_t file_length = 0; wlrh_t *params_in = (wlrh_t *) indata; /* The logrecord is stored in the indata buffer right after the * wlrh_t structure */ char *logrecord = (char *) (indata + sizeof(wlrh_t)); int *errno_out_p = (int *) outdata; *errno_out_p = 0; //#define LLD_DELAY_WRTST /* LLDTEST */ #ifdef LLD_DELAY_WRTST /* Make "file system" hang for n sec at first write */ static bool lld_once_f = true; const unsigned int lld_sleep_sec = 10; #endif TRACE_ENTER(); retry: rc = write(params_in->fd, &logrecord[bytes_written], params_in->record_size - bytes_written); if (rc == -1) { if (errno == EINTR) goto retry; LOG_ER("%s - write FAILED: %s",__FUNCTION__, strerror(errno)); *errno_out_p = errno; goto done; } else { /* Handle partial writes */ bytes_written += rc; if (bytes_written < params_in->record_size) goto retry; } #ifdef LLD_DELAY_WRTST /* LLDTEST Wait first time thread is used */ if (strstr(logrecord, "xxx")) { if (lld_once_f == true) { lld_once_f = false; TRACE("LLDTEST xxx Hang write"); //TRACE("LLDTEST: logrecord \"%s\"",logrecord); sleep(lld_sleep_sec); TRACE("LLDTEST End of sleep"); } } if (strstr(logrecord, "yyy")) { lld_once_f = true; TRACE("LLDTEST yyy Rearmed Hang write"); } #endif /* If the thread was hanging and has timed out and the log record was * written it is invalid and shall be removed from file (log service has * returned SA_AIS_TRY_AGAIN). */ osaf_mutex_lock_ordie(&lgs_ftcom_mutex); /* LOCK */ if (*timeout_f == true) { TRACE("Timeout, removing last log record"); file_length = lseek(params_in->fd, -bytes_written, SEEK_END); if (file_length != -1) { do { rc = ftruncate(params_in->fd, file_length); } while ((rc == -1) && (errno == EINTR)); } if (file_length == -1) { LOG_WA("%s - lseek error, Could not remove redundant log record, %s", __FUNCTION__,strerror(errno)); } else if (rc == -1) { LOG_WA("%s - ftruncate error, Could not remove redundant log record, %s", __FUNCTION__,strerror(errno)); } } osaf_mutex_unlock_ordie(&lgs_ftcom_mutex); /* UNLOCK */ done: TRACE_LEAVE2("rc = %d",rc); return rc; }
uint32_t mds_lib_req(NCS_LIB_REQ_INFO *req) { char *p_field = NULL; uint32_t node_id = 0, cluster_id, mds_tipc_ref = 0; /* this mds tipc ref is random num part of the TIPC id */ uint32_t status = NCSCC_RC_SUCCESS; NCS_SEL_OBJ destroy_ack_obj; char *ptr; switch (req->i_op) { case NCS_LIB_REQ_CREATE: mds_mutex_init_once(); osaf_mutex_lock_ordie(&gl_mds_library_mutex); if (gl_mds_mcm_cb != NULL) { syslog(LOG_ERR, "MDS_LIB_CREATE : MDS is already initialized"); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return NCSCC_RC_FAILURE; } /* Initialize mcm database */ mds_mcm_init(); /* Extract parameters from req and fill adest and pcon_id */ /* Get Node_id */ p_field = (char *)ncs_util_search_argv_list(req->info.create.argc, req->info.create.argv, "NODE_ID="); if (p_field != NULL) { if (sscanf(p_field + strlen("NODE_ID="), "%d", &node_id) != 1) { syslog(LOG_ERR, "MDS_LIB_CREATE : Problem in NODE_ID argument\n"); mds_mcm_destroy(); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return m_LEAP_DBG_SINK(NCSCC_RC_FAILURE); } } /* Get Cluster_id */ p_field = NULL; p_field = (char *)ncs_util_search_argv_list(req->info.create.argc, req->info.create.argv, "CLUSTER_ID="); if (p_field != NULL) { if (sscanf(p_field + strlen("CLUSTER_ID="), "%d", &cluster_id) != 1) { syslog(LOG_ERR, "MDS_LIB_CREATE : Problem in CLUSTER_ID argument\n"); mds_mcm_destroy(); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return m_LEAP_DBG_SINK(NCSCC_RC_FAILURE); } } /* Get tipc_mcast_enabled */ if ((ptr = getenv("MDS_TIPC_MCAST_ENABLED")) != NULL) { tipc_mcast_enabled = atoi(ptr); if (tipc_mcast_enabled != false) tipc_mcast_enabled = true; m_MDS_LOG_DBG("MDS_TIPC_MCAST_ENABLED: %d Set argument \n",tipc_mcast_enabled); } /* to use cluster id in mds prefix? */ /* Get gl_mds_log_level */ /* setting MDS_LOG_LEVEL from environment variable if given */ if ((ptr = getenv("MDS_LOG_LEVEL")) != NULL) { gl_mds_log_level = atoi(ptr); } else { p_field = NULL; p_field = (char *)ncs_util_search_argv_list(req->info.create.argc, req->info.create.argv, "MDS_LOG_LEVEL="); if (p_field != NULL) { if (sscanf(p_field + strlen("MDS_LOG_LEVEL="), "%d", &gl_mds_log_level) != 1) { syslog(LOG_ERR, "MDS_LIB_CREATE : Problem in MDS_LOG_LEVEL argument\n"); mds_mcm_destroy(); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return m_LEAP_DBG_SINK(NCSCC_RC_FAILURE); } } } /* gl_mds_log_level consistency check */ if (gl_mds_log_level > 5 || gl_mds_log_level < 1) { /* gl_mds_log_level specified is outside range so reset to Default = 3 */ gl_mds_log_level = 3; } /* Get gl_mds_checksum */ /* setting MDS_CHECKSUM from environment variable if given */ if ((ptr = getenv("MDS_CHECKSUM")) != NULL) { gl_mds_checksum = atoi(ptr); } else { p_field = NULL; p_field = (char *)ncs_util_search_argv_list(req->info.create.argc, req->info.create.argv, "MDS_CHECKSUM="); if (p_field != NULL) { if (sscanf(p_field + strlen("MDS_CHECKSUM="), "%d", &gl_mds_checksum) != 1) { syslog(LOG_ERR, "MDS_LIB_CREATE : Problem in MDS_CHECKSUM argument\n"); mds_mcm_destroy(); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return m_LEAP_DBG_SINK(NCSCC_RC_FAILURE); } } } /* gl_mds_checksum consistency check */ if (gl_mds_checksum != 1) { /* gl_mds_checksum specified is not 1 so reset to 0 */ gl_mds_checksum = 0; } /*****************************/ /* Timer value Configuration */ /*****************************/ /* Get Subscription timer value */ p_field = NULL; p_field = (char *)ncs_util_search_argv_list(req->info.create.argc, req->info.create.argv, "SUBSCRIPTION_TMR_VAL="); if (p_field != NULL) { if (sscanf(p_field + strlen("SUBSCRIPTION_TMR_VAL="), "%d", &MDS_SUBSCRIPTION_TMR_VAL) != 1) { syslog(LOG_ERR, "MDS_LIB_CREATE : Problem in SUBSCRIPTION_TMR_VAL argument\n"); mds_mcm_destroy(); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return m_LEAP_DBG_SINK(NCSCC_RC_FAILURE); } } /* Get Await Active timer value */ p_field = NULL; p_field = (char *)ncs_util_search_argv_list(req->info.create.argc, req->info.create.argv, "AWAIT_ACTIVE_TMR_VAL="); if (p_field != NULL) { if (sscanf(p_field + strlen("AWAIT_ACTIVE_TMR_VAL="), "%d", &MDS_AWAIT_ACTIVE_TMR_VAL) != 1) { syslog(LOG_ERR, "MDS_LIB_CREATE : Problem in AWAIT_ACTIVE_TMR_VAL argument\n"); mds_mcm_destroy(); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return m_LEAP_DBG_SINK(NCSCC_RC_FAILURE); } } /* Get Quiesced timer value */ p_field = NULL; p_field = (char *)ncs_util_search_argv_list(req->info.create.argc, req->info.create.argv, "QUIESCED_TMR_VAL="); if (p_field != NULL) { if (sscanf(p_field + strlen("QUIESCED_TMR_VAL="), "%d", &MDS_QUIESCED_TMR_VAL) != 1) { syslog(LOG_ERR, "MDS_LIB_CREATE : Problem in QUIESCED_TMR_VAL argument\n"); mds_mcm_destroy(); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return m_LEAP_DBG_SINK(NCSCC_RC_FAILURE); } } /* Get Reassembly timer value */ p_field = NULL; p_field = (char *)ncs_util_search_argv_list(req->info.create.argc, req->info.create.argv, "REASSEMBLE_TMR_VAL="); if (p_field != NULL) { if (sscanf(p_field + strlen("REASSEMBLE_TMR_VAL="), "%d", &MDTM_REASSEMBLE_TMR_VAL) != 1) { syslog(LOG_ERR, "MDS_LIB_CREATE : Problem in REASSEMBLE_TMR_VAL argument\n"); mds_mcm_destroy(); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return m_LEAP_DBG_SINK(NCSCC_RC_FAILURE); } } mds_init_transport(); /* Invoke MDTM-INIT. */ status = mds_mdtm_init(node_id, &mds_tipc_ref); if (status != NCSCC_RC_SUCCESS) { /* todo cleanup */ return NCSCC_RC_FAILURE; } gl_mds_mcm_cb->adest = m_MDS_GET_ADEST_FROM_NODE_ID_AND_PROCESS_ID(node_id, mds_tipc_ref); get_adest_details(gl_mds_mcm_cb->adest, gl_mds_mcm_cb->adest_details); /* Initialize logging */ { char buff[50], pref[50]; snprintf(buff, sizeof(buff), PKGLOGDIR "/mds.log"); memset(pref, 0 ,sizeof(pref)); mds_log_init(buff, pref); } osaf_mutex_unlock_ordie(&gl_mds_library_mutex); break; case NCS_LIB_REQ_DESTROY: /* STEP 1: Invoke MDTM-Destroy. */ /* mds_mdtm_destroy (); */ /* STEP 2: Destroy MCM-CB; */ /* ncs_patricia_tree_destroy(&gl_mds_mcm_cb->vdest_list); */ /* m_MMGR_FREE_MDS_CB(gl_mds_mcm_cb); */ m_NCS_SEL_OBJ_CREATE(&destroy_ack_obj); /* Post a dummy message to MDS thread to guarantee that it wakes up (and thereby sees the destroy_ind) */ if (mds_destroy_event(destroy_ack_obj) == NCSCC_RC_FAILURE) { m_NCS_SEL_OBJ_DESTROY(&destroy_ack_obj); return NCSCC_RC_FAILURE; } /* Wait for indication from MDS thread that it is ok to kill it */ osaf_poll_one_fd(m_GET_FD_FROM_SEL_OBJ(destroy_ack_obj), 70000); /* 70 seconds */ m_MDS_LOG_DBG("LIB_DESTROY:Destroy ack from MDS thread in 70 s"); /* Take the lock before killing the thread */ osaf_mutex_lock_ordie(&gl_mds_library_mutex); /* Now two things have happened (1) MDS thread has acked the destroy-event. So it will do no further things beyound MDS unlock (2) We have obtained MDS-Lock. So, even the un-lock by MDS thead is completed Now we can proceed with the systematic destruction of MDS internal Data */ /* Free the objects related to destroy-indication. The destroy mailbox event will be automatically freed by MDS processing or during MDS mailbox destruction. Since we will be destroying the MDS-thread, the following selection-object can no longer be accessed. Hence, it is safe and correct to destroy it now */ m_NCS_SEL_OBJ_DESTROY(&destroy_ack_obj); memset(&destroy_ack_obj, 0, sizeof(destroy_ack_obj)); /* Destroy info */ /* Sanity check */ if (gl_mds_mcm_cb == NULL) { syslog(LOG_ERR, "MDS_LIB_DESTROY : MDS is already Destroyed"); osaf_mutex_unlock_ordie(&gl_mds_library_mutex); return NCSCC_RC_FAILURE; } status = mds_mdtm_destroy(); if (status != NCSCC_RC_SUCCESS) { /* todo anything? */ } status = mds_mcm_destroy(); if (status != NCSCC_RC_SUCCESS) { /* todo anything? */ } /* Just Unlock the lock, Lock is never destroyed */ osaf_mutex_unlock_ordie(&gl_mds_library_mutex); break; default: break; } return NCSCC_RC_SUCCESS; }
/** * Handler for mds register requests * Note: executed by and in context of the auth thread! * Communicates with the main thread (where the * real work is done) to get outcome of initialization request which is then * sent back to the client. * @param fd * @param creds credentials for client */ static void mds_register_callback(int fd, const struct ucred *creds) { uint8_t buf[32]; uint8_t *p = buf; TRACE_ENTER2("fd:%d, pid:%u", fd, creds->pid); int n = recv(fd, buf, sizeof(buf), 0); if (n == -1) { syslog(LOG_ERR, "%s: recv failed - %s", __FUNCTION__, strerror(errno)); goto done; } if (n != 16) { syslog(LOG_ERR, "%s: recv failed - %d bytes", __FUNCTION__, n); goto done; } int type = ncs_decode_32bit(&p); NCSMDS_SVC_ID svc_id = ncs_decode_32bit(&p); MDS_DEST mds_dest = ncs_decode_64bit(&p); TRACE("mds: received %d from %"PRIx64", pid %d", type, mds_dest, creds->pid); if (type == MDS_REGISTER_REQ) { osaf_mutex_lock_ordie(&gl_mds_library_mutex); MDS_PROCESS_INFO *info = mds_process_info_get(mds_dest, svc_id); if (info == NULL) { MDS_PROCESS_INFO *info = calloc(1, sizeof(MDS_PROCESS_INFO)); osafassert(info); info->mds_dest = mds_dest; info->svc_id = svc_id; info->uid = creds->uid; info->pid = creds->pid; info->gid = creds->gid; int rc = mds_process_info_add(info); osafassert(rc == NCSCC_RC_SUCCESS); } else { /* when can this happen? */ LOG_NO("%s: dest %"PRIx64" already exist", __FUNCTION__, mds_dest); // just update credentials info->uid = creds->uid; info->pid = creds->pid; info->gid = creds->gid; } osaf_mutex_unlock_ordie(&gl_mds_library_mutex); p = buf; uint32_t sz = ncs_encode_32bit(&p, MDS_REGISTER_RESP); sz += ncs_encode_32bit(&p, 0); // result OK if ((n = send(fd, buf, sz, 0)) == -1) syslog(LOG_ERR, "%s: send to pid %d failed - %s", __FUNCTION__, creds->pid, strerror(errno)); } else if (type == MDS_UNREGISTER_REQ) { osaf_mutex_lock_ordie(&gl_mds_library_mutex); MDS_PROCESS_INFO *info = mds_process_info_get(mds_dest, svc_id); if (info != NULL) { (void)mds_process_info_del(info); } osaf_mutex_unlock_ordie(&gl_mds_library_mutex); p = buf; uint32_t sz = ncs_encode_32bit(&p, MDS_UNREGISTER_RESP); sz += ncs_encode_32bit(&p, 0); // result OK if ((n = send(fd, buf, sz, 0)) == -1) syslog(LOG_ERR, "%s: send to pid %d failed - %s", __FUNCTION__, creds->pid, strerror(errno)); } else { syslog(LOG_ERR, "%s: recv failed - wrong type %d", __FUNCTION__, type); goto done; } done: TRACE_LEAVE(); }
/*************************************************************************** * * ncs_os_process_execute_timed * * Description: To execute a module in a new process with time-out. * * Synopsis: * * Call Arguments: * req - Request parameters. * * Returns: * Success or failure * * Notes: * **************************************************************************/ uint32_t ncs_os_process_execute_timed(NCS_OS_PROC_EXECUTE_TIMED_INFO *req) { int count; int pid; NCS_OS_ENVIRON_SET_NODE *node = NULL; if ((req->i_script == NULL) || (req->i_cb == NULL)) return NCSCC_RC_FAILURE; if (req->i_set_env_args == NULL) count = 0; else { count = req->i_set_env_args->num_args; node = req->i_set_env_args->env_arg; } m_NCS_LOCK(&module_cb.tree_lock, NCS_LOCK_WRITE); if (module_cb.init != true) { /* this will initializes the execute module control block */ if (start_exec_mod_cb() != NCSCC_RC_SUCCESS) { m_NCS_UNLOCK(&module_cb.tree_lock, NCS_LOCK_WRITE); syslog(LOG_ERR, "%s: start_exec_mod_cb failed", __FUNCTION__); return NCSCC_RC_FAILURE; } } osaf_mutex_lock_ordie(&s_cloexec_mutex); if ((pid = fork()) == 0) { /* ** Make sure forked processes have default scheduling class ** independent of the callers scheduling class. */ struct sched_param param = {.sched_priority = 0 }; if (sched_setscheduler(0, SCHED_OTHER, ¶m) == -1) syslog(LOG_ERR, "%s: Could not setscheduler: %s", __FUNCTION__, strerror(errno)); /* set the environment variables */ for (; count > 0; count--) { setenv(node->name, node->value, node->overwrite); node++; } /* By default we close all inherited file descriptors in the child */ if (getenv("OPENSAF_KEEP_FD_OPEN_AFTER_FORK") == NULL) { /* Close all inherited file descriptors */ int i = sysconf(_SC_OPEN_MAX); if (i == -1) { syslog(LOG_ERR, "%s: sysconf failed - %s", __FUNCTION__, strerror(errno)); exit(EXIT_FAILURE); } for (i--; i >= 0; --i) (void) close(i); /* close all descriptors */ /* Redirect standard files to /dev/null */ if (freopen("/dev/null", "r", stdin) == NULL) syslog(LOG_ERR, "%s: freopen stdin failed - %s", __FUNCTION__, strerror(errno)); if (freopen("/dev/null", "w", stdout) == NULL) syslog(LOG_ERR, "%s: freopen stdout failed - %s", __FUNCTION__, strerror(errno)); if (freopen("/dev/null", "w", stderr) == NULL) syslog(LOG_ERR, "%s: freopen stderr failed - %s", __FUNCTION__, strerror(errno)); } /* RUNASROOT gives the OpenSAF user a possibility to maintain the < 4.2 behaviour. * For example the UML environment needs this because of its simplified user management. * OpenSAF processes will otherwise be started as the real host user and will * have problems e.g. writing PID files to the root owned directory. */ #ifndef RUNASROOT /* Check owner user ID of file and change group and user accordingly */ { struct stat buf; if (stat(req->i_script, &buf) == 0) { if (setgid(buf.st_gid) == -1) syslog(LOG_ERR, "setgid %u failed - %s", buf.st_gid, strerror(errno)); if (setuid(buf.st_uid) == -1) syslog(LOG_ERR, "setuid %u failed - %s", buf.st_uid, strerror(errno)); } else { syslog(LOG_ERR, "Could not stat %s - %s", req->i_script, strerror(errno)); exit(128); } } #endif /* child part */ if (execvp(req->i_script, req->i_argv) == -1) { syslog(LOG_ERR, "%s: execvp '%s' failed - %s", __FUNCTION__, req->i_script, strerror(errno)); exit(128); } } else if (pid > 0) { /* * Parent - Add new pid in the tree, * start a timer, Wait for a signal from child. */ osaf_mutex_unlock_ordie(&s_cloexec_mutex); if (NCSCC_RC_SUCCESS != add_new_req_pid_in_list(req, pid)) { m_NCS_UNLOCK(&module_cb.tree_lock, NCS_LOCK_WRITE); syslog(LOG_ERR, "%s: failed to add PID", __FUNCTION__); return NCSCC_RC_FAILURE; } } else { /* fork ERROR */ syslog(LOG_ERR, "%s: fork failed - %s", __FUNCTION__, strerror(errno)); osaf_mutex_unlock_ordie(&s_cloexec_mutex); m_NCS_UNLOCK(&module_cb.tree_lock, NCS_LOCK_WRITE); return NCSCC_RC_FAILURE; } m_NCS_UNLOCK(&module_cb.tree_lock, NCS_LOCK_WRITE); return NCSCC_RC_SUCCESS; }