

![]() | Start a set with this search |
![]() | Include this search in one of my sets |
![]() | Exclude this search from one of my sets |
![]() | Permalink to these results Paste this link in email or IM: |
| Atom feed for tracking future search results Paste this URL into your reader: |
4 messages in net.java.dev.jna.usersRe: [jna-users] Using setProtected un...| From | Sent On | Attachments |
|---|---|---|
| Jonathan Newell | Jan 8, 2008 6:50 pm | |
| Jonathan Newell | Jan 9, 2008 5:50 am | |
| Timothy Wall | Jan 12, 2008 11:29 am | |
| Timothy Wall | Jan 21, 2008 1:45 am |

![]() | Permalink for this message Paste this link in email or IM: |
![]() | Permalink for this thread Paste this link in email or IM: |
| Atom feed for this thread Paste this URL into your reader: |
| Subject: | Re: [jna-users] Using setProtected under win32 | Actions... |
|---|---|---|
| From: | Timothy Wall (twal...@dev.java.net) | |
| Date: | Jan 21, 2008 1:45:17 am | |
| List: | net.java.dev.jna.users | |
On Jan 9, 2008, at 8:50 AM, Jonathan Newell wrote:
The basic scenario I'm running is that the dll has various (1000s) plugins, some of which work and some of which don't - I want to be able to detect those that don't via an exception in java and drive on (logging the fact that a specific plugin was bad).
I've checked out and built trunk (revision 439), but after calling Native.setProtected(true) the vm still crashes when making the call through to the external dll. Looking at the code, this seems to be in the dispatch method:
(in dispatch.c) PSTART(); ffi_call(&cif, FFI_FN(func), resP, ffi_values); PEND(); if (preserve_last_error) { update_last_error(env, GET_LAST_ERROR()); }
The win32 specific protection code is very different to the other protection code, and I wonder why this is the case. In particular I'm not convinced that the atempt to unwind the stack is very useful, if I'm reading it right it will only go back one frame which means that if the exception occurs more than one frame down from where the exception handler is installed then it will restart too deep in the stack.
The unwind restores the stack to its state when the handler was installed. This is pretty much the same thing that setjmp/longjmp does (although apparently there's some difference if you're getting different results with setjmp/longjmp. One difference is that setjmp/ longjmp may restore more processor state.
I've reworked the code to use setjmp/longjmp (as with the other exception handling) and it seems to work better:
(in protect.h) #ifdef _WIN32 #include <excpt.h> #include <setjmp.h>
static jmp_buf context;
static EXCEPTION_DISPOSITION __cdecl exc_handler(struct _EXCEPTION_RECORD* exception_record, void *establisher_frame, struct _CONTEXT *context_record, void* dispatcher_context) { longjmp(context, exception_record->ExceptionCode); }
#define PROTECTED_START() \ EXCEPTION_REGISTRATION ex_reg; \ int _error = 0; \ if (PROTECT) { \ ex_reg.handler = exc_handler; \ asm volatile ("movl %%fs:0, %0" : "=r" (ex_reg.prev)); \ asm volatile ("movl %0, %%fs:0" : : "r" (&ex_reg)); \ if ((_error = setjmp(context) != 0)) { \ goto _exc_caught; \ } \ }
#define PROTECTED_END(ONERR) do { \ if (!_error) \ goto _remove_handler; \ _exc_caught: \ ONERR; \ _remove_handler: \ if (PROTECT) { asm volatile ("movl %0, %%fs:0" : : "r" (ex_reg.prev)); } \ } while(0)
#else...
This still uses the windows structured exception handling. The only issue I find is that I have to call Native.setPreserveLastError (false) if I want to actually receive the error raised in ONERR, otherwise the error preserving after the ffi_call actually wipes out the error (it is not a safe post-exception JNI operation).
I'd love some comments on the above, specifically whether people think it is a safe approach. I'm not a C programmer (in fact I've basically had to learn C from scratch over the past 24 hours to do this), so I might be missing something obvious or doing something really stupid, apologies in advance if this is the case (I specifically apologize if I've misunderstood the existing stack unwinding code, it was well beyond me and I may be doing it a disservice!).
I don't think this would be any worse than just restoring the stack pointer, and apparently, in your case, produces better results.







