Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible deadlock in DispatchWorker #2

Closed
EvenAR opened this issue Aug 8, 2017 · 1 comment
Closed

Possible deadlock in DispatchWorker #2

EvenAR opened this issue Aug 8, 2017 · 1 comment

Comments

@EvenAR
Copy link
Owner

EvenAR commented Aug 8, 2017

The DispatchWorker, which is a subclass of Nan::AsyncWorker (runs on a separate thread), some times stops receiving data. Not very often - it happens like 1 out of 50 times after I start example.js

The DispatchWorker has an infinite loop where it reads data from the active connection (if any) and notifies the main thread once it receieves something interesting (data or an NT_ERROR). The main thread is notified using uv_async_send (libuv), which later at some time wakes up the messageReceiver which extracts the data received from SimConnect. A SimConnect dispatch contains pointers and data which only lives until the next dispatch is loaded. Therefore, after DispatcWorker has notified the main thread, it must wait for the main thread to signal that it has finished reading the data before it proceeds with receiving dispatces.

It looks like the while(true)-loop stops running, as VS no longer stops if I set a breakpoint in the loop.

I'm not too experienced with multithreading, so if anyone have an idea of what is wrong, I'll be very thankful! I suspect there is a deadlock which is caused by uv_cond_signal(&cv) not being called. Some possible reasons I can think of:

  • Something wrong is going on in the extraction of the dispatch data (messageReceiver). The strange thing is, there are no errors or exceptions that I can see. I am running the debug-version of Node.JS through Visual Studio.
  • The mutex and condition variable is used incorrectly.
  • The V8 SDK is used incorrectly, which causes a break before uv_cond_signal(&cv) is called. Still, I have no indication from Visual Studio about any errors.

I have pasted a short version of the code below. Full code here


class DispatchWorker : public Nan::AsyncWorker {
public:
	DispatchWorker(Nan::Callback *callback) : AsyncWorker(callback) {

	}
	~DispatchWorker() {}

	void Execute() {
		uv_async_init(loop, &async, messageReceiver); // Must be called from worker thread

		while (true) {

			if (ghSimConnect) {
				SIMCONNECT_RECV* pData;
				DWORD cbData;

				HRESULT hr = SimConnect_GetNextDispatch(ghSimConnect, &pData, &cbData);

				if (SUCCEEDED(hr))
				{
					CallbackData data;
					data.pData = pData;
					data.cbData = cbData;
					data.ntstatus = STATUS_SUCCESS;
					async.data = &data;
					uv_mutex_lock(&mutex);
					uv_async_send(&async);
				
					// Wait for main thread to process the dispatch 
					uv_cond_wait(&cv, &mutex);
				}
				else if (NT_ERROR(hr)) {
					CallbackData data;
					data.ntstatus = (NTSTATUS)hr;
					async.data = &data;
					uv_mutex_lock(&mutex);
					uv_async_send(&async);

					// Wait for main thread to process the dispatch 
					uv_cond_wait(&cv, &mutex);
				}
			}
			else {
				Sleep(10);
			}
		}
	}
};

Runs on main thread (some time) after uv_async_send() is called

void messageReceiver(uv_async_t* handle) {

	Nan::HandleScope scope;
	v8::Isolate* isolate = v8::Isolate::GetCurrent();

	CallbackData* data = (CallbackData*)handle->data;

	// ..... extract data ....

	// The dispatch-worker can now continue
	uv_mutex_unlock(&mutex);
	uv_cond_signal(&cv);
}
@EvenAR
Copy link
Owner Author

EvenAR commented Aug 10, 2017

Ok, so using a semaphore instead now (7961518) and I have not been able to trigger the issue yet (🤞). I will wait a few days before I close this issue.

@EvenAR EvenAR closed this as completed Aug 12, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant