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, &notUsed) != 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);
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
/*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;
		}
	}
}
Exemplo n.º 5
0
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);
    }
}
Exemplo n.º 6
0
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;
}