void rpc_ss_destroy_callee_context ( dce_uuid_t *p_uuid, /* Pointer to UUID of context to be destroyed */ handle_t h, /* Binding handle */ error_status_t *result /* Function result */ ) /* Returns error_status_ok unless the UUID is not in the lookup table */ { rpc_client_handle_t close_client; /* NULL or client to stop monitoring */ #ifdef PERFMON RPC_SS_DESTROY_CALLEE_CONTEXT_N; #endif RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); DPRINT(("Seized context tables\n")); rpc_ss_lkddest_callee_context(p_uuid,&close_client,result); RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); if ((*result == error_status_ok) && (close_client != NULL)) { rpc_network_stop_monitoring(h, close_client, (error_status_t *) result); } #ifdef PERFMON RPC_SS_DESTROY_CALLEE_CONTEXT_X; #endif }
void rpc_ss_rundown_client ( /* [in] */ rpc_client_handle_t failed_client ) { error_status_t result; callee_client_entry_t *this_client; callee_context_entry_t *this_context; rpc_client_handle_t close_client = NULL; /* NULL or client to stop monitoring */ /* FIXME: is the volatility set correctly here? */ rpc_ss_rundown_list_elt * volatile rundown_list; rpc_ss_rundown_list_elt * volatile rundown_elt; rundown_list = NULL; #ifdef PERFMON RPC_SS_RUNDOWN_CLIENT_N; #endif RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); DPRINT(("Seized context tables\n")); for( this_client = &client_table[HASH_CLIENT_ID(failed_client)]; (this_client != NULL) && (close_client == NULL); this_client = this_client->next_h_client ) { if (this_client->client == failed_client) { while (this_client->ref_count != 0) { this_client->rundown_pending = idl_true; RPC_SS_THREADS_CONDITION_WAIT(&this_client->cond_var, &rpc_ss_context_table_mutex); /* Mutex has been released */ RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); } if (this_client->count == 0) { /* The manager closed the contexts while a rundown was pending */ rpc_ss_ctx_remove_client_entry(this_client); RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); #ifdef PERFMON RPC_SS_RUNDOWN_CLIENT_X; #endif return; } /* Need to clear the rundown pending flag so that the client entry can be deleted */ this_client->rundown_pending = idl_false; while (close_client == NULL) { /* Loop until all contexts for this client have been removed from the context table. Note that each iteration brings a different context to first_context position */ this_context = this_client->first_context; rundown_elt = (rpc_ss_rundown_list_elt *) malloc(sizeof(rpc_ss_rundown_list_elt)); if (rundown_elt == NULL) { RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); /* * rpc_m_ctxrundown_nomem * "Out of memory while trying to run down contexts of client %x" */ RPC_DCE_SVC_PRINTF (( DCE_SVC(RPC__SVC_HANDLE, "%x"), rpc_svc_libidl, svc_c_sev_error, rpc_m_ctxrundown_nomem, this_client )); return; } rundown_elt->rundown = this_context->rundown; rundown_elt->user_context = this_context->user_context; rundown_elt->next = rundown_list; rundown_list = rundown_elt; rpc_ss_lkddest_callee_context (&this_context->uuid,&close_client,&result); } } } RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); DPRINT(("Released context tables\n")); while (rundown_list != NULL) { if (rundown_list->rundown != NULL) { DCETHREAD_TRY (*(rundown_list->rundown))(rundown_list->user_context); DCETHREAD_CATCH_ALL(caught) /* * rpc_m_ctxrundown_exc * "Exception in routine at %x, running down context %x of client %x" */ RPC_DCE_SVC_PRINTF (( DCE_SVC(RPC__SVC_HANDLE, "%x%x%x"), rpc_svc_libidl, svc_c_sev_error, rpc_m_ctxrundown_exc, rundown_list->rundown, rundown_list->user_context, this_client )); DCETHREAD_ENDTRY } rundown_elt = rundown_list; rundown_list = rundown_list->next; free(rundown_elt); }