Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Race condition in JNI DvProvider code
09-12-2011, 03:54 PM
Post: #1
Race condition in JNI DvProvider code
If my application encounters a fatal problem while running a provider action, it throws an ActionError from the provider method invocation, then switches to another thread which disposes the provider and destroys the device.

Unfortunately the unpredictability of thread dispatching means that the DvProvider.dispose() call may execute before control returns back to the JNI code in the CallbackDvInvocation function (line 43 in Bindings/Java/DvProvider.c). This causes a crash at line 45 in DvProvider.c:

(*(ref->vm))->DetachCurrentThread(ref->vm);

because the 'ref' object has been freed by the code at line 90 of DvProvider.c when the dispose() call executed.

As an experiment I've tried modifying the code in the CallbackDvInvocation function to make a local copy of the 'vm' variable on the stack at the start of the function and use this local copy when calling DetachCurrentThread() instead of relying on the heap value being valid. This seems to work OK with no other ill effects elsewhere in the ohNet stack from returning back from an invocation after the provider has been destroyed.

I can't think of any reasonable way for me to delay my application's call to dispose the provider until after the code in line 45 of DvProvider.c has run. I have experimented with disabling the device in the hope that this may provide the necessary synchronization (i.e., that by the time the deviceDisabled() callback has run I would be guaranteed to be past line 45 in any outstanding invocations) but I haven't had any success with this.

At this point I'm inclined to think that modifying the JNI code as I have done in my experiment is the correct solution. This could be done just in this one case, or more pervasively in the JNI code whenever it uses a 'vm' pointer. The changes I have made to DVProvider.c are as follows:

After line 20, insert:
JavaVM *vm = ref->vm;

Change line 45 from:
(*(ref->vm))->DetachCurrentThread(ref->vm);
to:
(*vm)->DetachCurrentThread(vm);

Simon
Find all posts by this user
09-12-2011, 04:53 PM
Post: #2
RE: Race condition in JNI DvProvider code
Thanks. I've applied your suggested pattern throughout the JNI code.
Find all posts by this user


Forum Jump: