rpc exception
Gregory M. Turner
gmturner007 at ameritech.net
Thu May 1 00:26:16 CDT 2003
On Monday 21 April 2003 10:55 pm, Alexandre Julliard wrote:
> "Dimitrie O. Paun" <dpaun at rogers.com> writes:
> > Just like with threads, why not cross that bridge when we get there?
> > Is it really worth it to penalize 99% of the people? When we port to
> > another compiler, it will be a lot simpler to worry about those pieces
> > of code, rather than have no code at all.
>
> The difference with threads is that we know all platforms have some
> kind of threading, so we know that we can adapt the code when
> needed. I don't think any other C compiler supports local functions
> (even g++ doesn't AFAIK), so there won't be much hope of ever making
> it work. Of course we could decide to stop supporting other compilers,
> but I don't think everybody would be happy with that.
>
> > Also, not accepting code into Wine that depend on exception is one thing,
> > but what about Winelib? We can have the exception code commented out if
> > __WINESRC__ is defined, but at least lets get it in if it works, it will
> > plug a big Winelib hole.
>
> Sure, we can make the macros available for Winelib.
OK, folks, I think I may have a plan to create a portable __except, please let
me know your thoughts, as there are many places I might be going wrong. What
follows is a totally new approach compared to my old attempts; I haven't
tried to implement a similar implementation "plan" for __finally yet.
Allright, here goes, in crap / gibberish ("pseudocode") form:
/* GLOBAL structure instance somewhere (ntdll?) Thread-local */
typedef struct {
bool do_handler_bit;
DWORD exception_code;
jmp_buf jmp;
} SEH_TLS_TEMP;
SEH_TLS_TEMP SEH_TLS_TEMPS;
WINE_EXCEPTION_HANDLER_FUNC WineSEHHandler(args) {
if (setjmp(SEH_TLS_TEMPS.jmp)) {
switch(SEH_TLS_TEMPS.exception_code)
... /* the rest is like __wine_exception_handler in
ntdll/exception.c */
} else {
do_handler_bit = 0;
longjmp(exception_record_argument->jmpbuf, 0);
}
}
/* now here are the parts that would be in include/wine/exception.h */
/* exactly the same as __TRY, really just #define __try __TRY */
#define __try \
do { __WINE_FRAME __f; \
int __first = 1; \
for (;;) if (!__first) \
{ \
do {
#define __except(expr) \
} while(0); \
SEH_TLS_TEMPS.do_handler_bit = 0;
__wine_pop_frame( &__f.frame ); \
break; \
} else { \
__f.frame.Handler = (PEXCEPTION_HANDLER) WineSEHHandler; \
__f.u.filter = NULL; \
__wine_push_frame( &__f.frame ); \
if (setjmp( __f.jmp)) { \
int ecode; \
const __WINE_FRAME * const __eptr WINE_UNUSED = &__f; \
/* exception code hacks go here... */ \
if ((ecode = (expr)) != EXECUTE_HANDLER) { \
SEH_TLS_TEMPS.exception_code = ecode \
longjmp(SEH_TLS_TEMPS.jmp, 0); \
} \
RtlUnwind(...); \
__wine_pop_frame();
SEH_TLS_TEMPS.do_handler_bit = 1; \
break; \
} \
__first = 0; \
} \
} while (0); \
if (SEH_TLS_TEMPS.do_handler_bit)
This obviously is leaving some stuff out. For example, this wouldn't work
with nested exceptions. However, that seems possible to fix, if not by
abusing the jmp_buf right in the frame structure then by creating a stack of
SEH_TLS_TEMP structures instead of just a single instance, or maybe in some
other clever way like attaching the SEH_TLS_TEMP struct to the wine frame
struct.
What I'm more concerned about is the following:
A() runs setjmp, calls B(), which calls C(), which calls D(). A() would be
the user's function (whatever it is) and D() would be WineSEHHandler above.
D() runs setjmp again on a second jump buffer, and calls longjmp to do a
nonlocal goto into A().
Now:
(a) if the exception code runs, A() keeps running and eventually just
returns... will it properly release all the stack from B(), C() and so on or
is this a problem? I guess its OK since the SP just goes back to what it was
when I called setjmp, right?
(b) if the exception code doesn't run, A() runs longjmp again, to non-local
goto /back/ into D(), using the second jmp_buf. This returns normally and
would, I guess, expect to unwind the stack normally through C(), B() and so
on... (this is all ignoring the fact that flow-of-control was interrupted by
an exception, but for my purposes I don't think it matters).
Are either of these scenarios illegal (in wine)? If not, I think I can make
it work. Another concern would be that two longjmps are just too slow to be
used, but since that only occurs in an exception scenario I think it's OK...
Thoughts, flames, etc?
--
"Security is mostly superstition. It does not exist in nature,
nor do the children of men as a whole experience it. Avoiding
danger is no safer in the long run than outright exposure. Life is
either a daring adventure, or nothing. To keep our faces toward
change and behave like free spirits in the presence of fate is
strength undefeatable." --Helen Keller
gmt
More information about the wine-devel
mailing list