static void shutdown_a_thread(THREAD_CONTROL * theThreadControl) { int notUsed; THREAD_HANDLE theCurrentThread; /*Codes_SRS_OUTPROCESS_MODULE_17_027: [ This function shall ensure thread safety on execution. ]*/ if (Lock(theThreadControl->thread_lock) != LOCK_OK) { /*Codes_SRS_OUTPROCESS_MODULE_17_032: [ This function shall signal the messaging thread to close. ]*/ /*Codes_SRS_OUTPROCESS_MODULE_17_049: [ This function shall signal the outgoing gateway message thread to close. ]*/ /*Codes_SRS_OUTPROCESS_MODULE_17_050: [ This function shall signal the control thread to close. ]*/ LogError("not able to Lock, still setting the thread to finish"); theCurrentThread = theThreadControl->thread_handle; theThreadControl->thread_flag = THREAD_FLAG_STOP; } else { /*Codes_SRS_OUTPROCESS_MODULE_17_032: [ This function shall signal the messaging thread to close. ]*/ /*Codes_SRS_OUTPROCESS_MODULE_17_049: [ This function shall signal the outgoing gateway message thread to close. ]*/ /*Codes_SRS_OUTPROCESS_MODULE_17_050: [ This function shall signal the control thread to close. ]*/ theThreadControl->thread_flag = THREAD_FLAG_STOP; theCurrentThread = theThreadControl->thread_handle; (void)Unlock(theThreadControl->thread_lock); } /*Codes_SRS_OUTPROCESS_MODULE_17_033: [ This function shall wait for the messaging thread to complete. ]*/ /*Codes_SRS_OUTPROCESS_MODULE_17_051: [ This function shall wait for the outgoing gateway message thread to complete. ]*/ /*Codes_SRS_OUTPROCESS_MODULE_17_052: [ This function shall wait for the control thread to complete. ]*/ if (theCurrentThread != NULL && ThreadAPI_Join(theCurrentThread, ¬Used) != THREADAPI_OK) { LogError("unable to ThreadAPI_Join message thread, still proceeding in _Destroy"); } /*Codes_SRS_OUTPROCESS_MODULE_17_034: [ This function shall release all resources created by this module. ]*/ (void)Lock_Deinit(theThreadControl->thread_lock); }
int ProxyGateway_HaltWorkerThread ( REMOTE_MODULE_HANDLE remote_module ) { int result; /* Codes_SRS_PROXY_GATEWAY_027_045: [Prerequisite Check - If the `remote_module` parameter is `NULL`, then `ProxyGateway_HaltWorkerThread` shall return a non-zero value] */ if (NULL == remote_module) { LogError("%s: NULL parameter - remote_module!", __FUNCTION__); result = __LINE__; // Check to confirm message thread is running } else if (NULL == remote_module->message_thread) { /* Codes_SRS_PROXY_GATEWAY_027_046: [Prerequisite Check - If a worker thread does not exist, then `ProxyGateway_HaltWorkerThread` shall return a non-zero value] */ LogInfo("%s: Worker thread has not been initialized.", __FUNCTION__); result = __LINE__; /* Codes_SRS_PROXY_GATEWAY_027_047: [`ProxyGateway_HaltWorkerThread` shall obtain the thread mutex in order to signal the thread by calling `LOCK_RESULT Lock(LOCK_HANDLE handle)`] */ } else if (LOCK_OK != Lock(remote_module->message_thread->mutex)) { /* Codes_SRS_PROXY_GATEWAY_027_048: [If unable to obtain the mutex, then `ProxyGateway_HaltWorkerThread` shall return a non-zero value] */ LogError("%s: Unable to acquire mutex!", __FUNCTION__); result = __LINE__; } else { int thread_exit_result = -1; // Signal the message thread remote_module->message_thread->halt = true; /* Codes_SRS_PROXY_GATEWAY_027_049: [`ProxyGateway_HaltWorkerThread` shall release the thread mutex upon signalling by calling `LOCK_RESULT Unlock(LOCK_HANDLE handle)`] */ if (LOCK_OK != Unlock(remote_module->message_thread->mutex)) { /* Codes_SRS_PROXY_GATEWAY_027_050: [If unable to release the mutex, then `ProxyGateway_HaltWorkerThread` shall return a non-zero value] */ LogError("%s: Unable to release mutex!", __FUNCTION__); result = __LINE__; /* Codes_SRS_PROXY_GATEWAY_027_051: [`ProxyGateway_HaltWorkerThread` shall halt the thread by calling `THREADAPI_RESULT ThreadAPI_Join(THREAD_HANDLE handle, int * res)`] */ } else if (THREADAPI_OK != ThreadAPI_Join(remote_module->message_thread->thread, &thread_exit_result)) { /* Codes_SRS_PROXY_GATEWAY_027_052: [If unable to join the thread, then `ProxyGateway_HaltWorkerThread` shall return a non-zero value] */ LogError("%s: Unable to halt message thread!", __FUNCTION__); result = __LINE__; } else { /* Codes_SRS_PROXY_GATEWAY_027_053: [`ProxyGateway_HaltWorkerThread` shall free the thread mutex by calling `LOCK_RESULT Lock_Deinit(LOCK_HANDLE handle)`] */ /* Codes_SRS_PROXY_GATEWAY_027_054: [If unable to free the thread mutex, then `ProxyGateway_HaltWorkerThread` shall ignore the result and continue processing] */ (void)Lock_Deinit(remote_module->message_thread->mutex); /* Codes_SRS_PROXY_GATEWAY_027_055: [`ProxyGateway_HaltWorkerThread` shall free the memory allocated to the thread details] */ free(remote_module->message_thread); remote_module->message_thread = NULL; if (0 != thread_exit_result) { /* Codes_SRS_PROXY_GATEWAY_027_056: [If an error is returned from the worker thread, then `ProxyGateway_HaltWorkerThread` shall return the worker thread's error code] */ LogError("%s: Thread exited with fail code <%d>!", __FUNCTION__, thread_exit_result); result = thread_exit_result; } else { /* Codes_SRS_PROXY_GATEWAY_027_057: [If no errors are encountered, then `ProxyGateway_HaltWorkerThread` shall return zero] */ result = 0; } } } return result; }
/*returns 0 if success, otherwise __LINE__*/ static int stop_module(int publish_socket, BROKER_MODULEINFO* module_info) { int quit_result, close_result, thread_result, result; /*Codes_SRS_BROKER_17_021: [ This function shall send a quit signal to the worker thread by sending BROKER_MODULEINFO::quit_message_guid to the publish_socket. ]*/ /* send the unique quite id for this module */ if ((quit_result = nn_send(publish_socket, STRING_c_str(module_info->quit_message_guid), BROKER_GUID_SIZE, 0)) < 0) { /*Codes_SRS_BROKER_17_015: [ This function shall close the BROKER_MODULEINFO::receive_socket. ]*/ /* at the cost of a data race, we will close the socket to terminate the thread */ nn_close(module_info->receive_socket); LogError("unable to peacefully close thread for module [%p], nn_send error [%d], taking harsher methods", module_info, quit_result); } else { /*Codes_SRS_BROKER_02_001: [ Broker_RemoveModule shall lock BROKER_MODULEINFO::socket_lock. ]*/ if (Lock(module_info->socket_lock) != LOCK_OK) { /*Codes_SRS_BROKER_17_015: [ This function shall close the BROKER_MODULEINFO::receive_socket. ]*/ /* at the cost of a data race, we will close the socket to terminate the thread */ nn_close(module_info->receive_socket); LogError("unable to peacefully close thread for module [%p], Lock error, taking harsher methods", module_info ); } else { /*Codes_SRS_BROKER_17_015: [ This function shall close the BROKER_MODULEINFO::receive_socket. ]*/ close_result = nn_close(module_info->receive_socket); if (close_result < 0) { LogError("Receive socket close failed for module at item [%p] failed", module_info); } else { /*all is fine, thread will eventually stop and be joined*/ } /*Codes_SRS_BROKER_02_003: [ After closing the socket, Broker_RemoveModule shall unlock BROKER_MODULEINFO::info_lock. ]*/ if (Unlock(module_info->socket_lock) != LOCK_OK) { LogError("unable to unlock socket lock"); } } } /*Codes_SRS_BROKER_13_104: [The function shall wait for the module's thread to exit by joining BROKER_MODULEINFO::thread via ThreadAPI_Join. ]*/ if (ThreadAPI_Join(module_info->thread, &thread_result) != THREADAPI_OK) { result = __LINE__; LogError("ThreadAPI_Join() returned an error."); } else { result = 0; } return result; }
static void wait_worker_thread(TRANSPORT_HANDLE_DATA * transportData) { if (transportData->workerThreadHandle != NULL) { int res; /*Codes_SRS_IOTHUBTRANSPORT_17_027: [ If handle list is empty, IoTHubTransport_EndWorkerThread shall be joined. ]*/ if (ThreadAPI_Join(transportData->workerThreadHandle, &res) != THREADAPI_OK) { LogError("ThreadAPI_Join failed"); } else { transportData->workerThreadHandle = NULL; } } }
static void SimulatorModule_Destroy(MODULE_HANDLE moduleHandle) { if (moduleHandle == NULL) { LogError("Destroying a NULL module"); } else { SIMULATOR_MODULE_HANDLE * module = (SIMULATOR_MODULE_HANDLE *)moduleHandle; module->thread_flag = false; int thread_result; (void)ThreadAPI_Join(module->main_thread, &thread_result); if (thread_result != 0) { LogInfo("Thread ended with non-zero result: %d", thread_result); } free(module->device_id); free(module->psuedo_random_buffer); free(module); } }
void IoTHubMessaging_Close(IOTHUB_MESSAGING_CLIENT_HANDLE messagingClientHandle) { if (messagingClientHandle == NULL) { /*Codes_SRS_IOTHUBMESSAGING_12_021: [ If messagingClientHandle is NULL, IoTHubMessaging_Close shall return IOTHUB_MESSAGING_INVALID_ARG. ]*/ LogError("NULL messagingClientHandle"); } else { IOTHUB_MESSAGING_CLIENT_INSTANCE* iotHubMessagingClientInstance = (IOTHUB_MESSAGING_CLIENT_INSTANCE*)messagingClientHandle; /*Codes_SRS_IOTHUBMESSAGING_12_022: [ IoTHubMessaging_Close shall be made thread-safe by using the lock created in IoTHubMessaging_Create. ]*/ if (Lock(iotHubMessagingClientInstance->LockHandle) != LOCK_OK) { LogError("Could not acquire lock"); iotHubMessagingClientInstance->StopThread = 1; /*setting it even when Lock fails*/ } else { iotHubMessagingClientInstance->StopThread = 1; /*Codes_SRS_IOTHUBMESSAGING_12_022: [ IoTHubMessaging_Close shall be made thread-safe by using the lock created in IoTHubMessaging_Create. ]*/ (void)Unlock(iotHubMessagingClientInstance->LockHandle); } if (iotHubMessagingClientInstance->ThreadHandle != NULL) { int res; /*Codes_SRS_IOTHUBMESSAGING_12_013: [ The thread created as part of executing IoTHubMessaging_SendAsync shall be joined. ]*/ if (ThreadAPI_Join(iotHubMessagingClientInstance->ThreadHandle, &res) != THREADAPI_OK) { LogError("ThreadAPI_Join failed"); } } /*Codes_SRS_IOTHUBMESSAGING_12_024: [ IoTHubMessaging_Close shall call IoTHubMessaging_LL_Close, while passing the IOTHUB_MESSAGING_HANDLE handle created by IoTHubMessaging_Create ]*/ IoTHubMessaging_LL_Close(messagingClientHandle->IoTHubMessagingHandle); } }
static MODULE_HANDLE Outprocess_Create(BROKER_HANDLE broker, const void* configuration) { OUTPROCESS_HANDLE_DATA * module; if ( (broker == NULL) || (configuration == NULL) ) { /*Codes_SRS_OUTPROCESS_MODULE_17_005: [ If broker or configuration are NULL, this function shall return NULL. ]*/ LogError("invalid arguments for outprcess module. broker=[%p], configuration = [%p]", broker, configuration); module = NULL; } else { OUTPROCESS_MODULE_CONFIG * config = (OUTPROCESS_MODULE_CONFIG*)configuration; /*Codes_SRS_OUTPROCESS_MODULE_17_006: [ This function shall allocate memory for the MODULE_HANDLE. ]*/ module = (OUTPROCESS_HANDLE_DATA*)malloc(sizeof(OUTPROCESS_HANDLE_DATA)); if (module == NULL) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ LogError("allocation for module failed."); } else { /*Codes_SRS_OUTPROCESS_MODULE_17_007: [ This function shall intialize a lock for exclusive access to handle data. ]*/ module->handle_lock = Lock_Init(); if (module->handle_lock == NULL) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ LogError("unable to intialize module lock"); free(module); module = NULL; } else { /*Codes_SRS_OUTPROCESS_MODULE_17_042: [ This function shall initialize a queue for outgoing gateway messages. ]*/ module->outgoing_messages = MESSAGE_QUEUE_create(); if (module->outgoing_messages == NULL) { LogError("unable to create outgoing message queue"); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else { if (connection_setup(module, config) < 0) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ LogError("unable to set up connections"); connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else { THREAD_CONTROL default_thread = { NULL, NULL, 0 }; module->broker = broker; module->remote_message_wait = config->remote_message_wait; module->message_receive_thread = default_thread; module->message_send_thread = default_thread; module->control_thread = default_thread; module->async_create_thread = default_thread; module->lifecyle_model = config->lifecycle_model; /*Codes_SRS_OUTPROCESS_MODULE_17_041: [ This function shall intitialize a lock for each thread for thread management. ]*/ if ((module->message_receive_thread.thread_lock = Lock_Init()) == NULL) { connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else if ((module->control_thread.thread_lock = Lock_Init()) == NULL) { connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else if ((module->async_create_thread.thread_lock = Lock_Init()) == NULL) { connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->control_thread.thread_lock); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else if ((module->message_send_thread.thread_lock = Lock_Init()) == NULL) { connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->async_create_thread.thread_lock); Lock_Deinit(module->control_thread.thread_lock); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else if (save_strings(module, config) != 0) { connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->async_create_thread.thread_lock); Lock_Deinit(module->control_thread.thread_lock); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->message_send_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else { /*Codes_SRS_OUTPROCESS_MODULE_17_014: [ This function shall wait for a Create Response on the control channel. ]*/ if (ThreadAPI_Create(&(module->async_create_thread.thread_handle), outprocessCreate, module) != THREADAPI_OK) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ LogError("failed to spawn a thread"); module->async_create_thread.thread_handle = NULL; connection_teardown(module); delete_strings(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->async_create_thread.thread_lock); Lock_Deinit(module->control_thread.thread_lock); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->message_send_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else { int thread_result = -1; if (module->lifecyle_model == OUTPROCESS_LIFECYCLE_SYNC) { if (ThreadAPI_Join(module->async_create_thread.thread_handle, &thread_result) != THREADAPI_OK) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ LogError("Async create thread failed result=[%d]", thread_result); thread_result = -1; } else { /*Codes_SRS_OUTPROCESS_MODULE_17_015: [ This function shall expect a successful result from the Create Response to consider the module creation a success. ]*/ // async thread is done. } module->async_create_thread.thread_handle = NULL; } else { thread_result = 1; } if (thread_result < 0) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ connection_teardown(module); delete_strings(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->async_create_thread.thread_lock); Lock_Deinit(module->control_thread.thread_lock); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->message_send_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } } } } } } } } return module; }