Does wine have a posix threads "emulation" with which TRY/EXCEPT/CATCH will work?

Luke Kenneth Casson Leighton lkcl at lkcl.net
Wed Jan 26 16:14:59 CST 2005


thank you rob.

i'm attaching some example code - it's from client/perf.c.

after looking at these closely, i believe it would be straightforward
to #define CATCH to __EXCEPT etc. and to rewrite the FreeDCE __EXCEPT
argument as a function rather than a structure.


dcethreads provides a CATCH macro - you are expected to provide
a catcher for _one_ particular exception type.  you're expected
to roll these one after another: the macro expands to

	"} else if exc_matches(...) { "

basically, i think the way that the Wine code does it, the CATCH
possibilities are "rolled" into one EXCEPT - is that correct?

or can you do more than one EXCEPT (even if the function says "i
accept more than one type of exception - visa _or_ marstercaaard")

so if the FreeDCE CATCH exceptions were turned into EXCEPT-style
functions, on a "#ifdef / ./configure --with-wine-exceptions" basis,
i think that'd work.

this raises a further question, which i apologise for not being
able to work out from looking at the macros.

is it possible to do this:

	__TRY {
		/* do something horrible */
	}
	__EXCEPT(exception_1) {
		printf("this is exception 1\n");
	}
	__EXCEPT(exception_2) {
		printf("this is exception 1\n");
	}
	ENDTRY


secondary question: does Wine's exception handling cope with "stacked"
exceptions and "fall-through"?

if there are "nested" __TRY / __EXCEPT blocks, and an exception is
not covered by the "inner" exception handlers, will it go through
to the "outer" ones?

ta rob.

l.

On Wed, Jan 26, 2005 at 03:11:36PM -0600, Robert Shearman wrote:
> Luke Kenneth Casson Leighton wrote:
> 
> >hi,
> >
> >i would like to check something which, if it is the case,
> >may make porting FreeDCE to wine a no-brainer.
> >
> >i notice that there exists pthread emulation in Wine: it
> >says so at the top of wine/dlls/kernel/pthread.c
> >
> >can i therefore expect the following things:
> >
> >1) the attached test program to compile and work under wine,
> >with a few macros and/or simple wrapper functions e.g. redirect
> >RAISE to RaiseException?
> >
> >2) a program that uses posix threads to also at the same time
> >be able to use Wine Exception routines/macros, try/except/catch?
> >
> >
> >... wouldn't it be ironic if Wine's pthreads emulation turned
> >out to provide exactly the posix draft 4 threading semantics
> >that FreeDCE programs expect?
> >
> >l.
> > 
> >
> 
> No, that program won't compile or run.
> Windows exception handling (SEH) requires you to have an exception 
> filter function so that you don't get, say, a STATUS_ACCESS_VIOLATION 
> exception when you are expecting an RPC_E_DISCONNECT exception.
> 
> You can see an example of Wine exception handling here:
> http://cvs.winehq.org/cvsweb/wine/dlls/user/lstr.c?rev=1.31&content-type=text/x-cvsweb-markup
> 
> Rob

-- 
--
<a href="http://lkcl.net">http://lkcl.net</a>
--
-------------- next part --------------
static void forwarding_test (test, argc, argv)

int                 test;
int                 argc;
char                *argv[];

{
    handle_t            rh;
    char                name[256];
    unsigned_char_p_t   name2;
    unsigned32          st;
    idl_boolean         global;
#define FSIZE 4000
    unsigned32       d[FSIZE];
    int                 i;
    unsigned32          sum, rsum;
    idl_char            result[256];
    unsigned_char_p_t   pstring;

	DO_NOT_CLOBBER(rh);
	DO_NOT_CLOBBER(rsum);
	 
    if (argc < 4)
    {
        usage(test);
    }

    global = argv[3][0] == 'y';
    rh = binding_from_string_binding(NULL, argv[2]);

    /*
     * Tell server to register the "perfb" interface.
     */
    perf_register_b(rh, global, &st);

    if (st != 0)
    {
        fprintf(stderr, "*** Can't register \"perfb\" interface - %s\n",
            error_text(st));
        exit(1);
    }

    TRY
    {
        if (! compat_mode)
        {
            /*
             * Clear the binding to the server and call resolve_binding.
             */
            binding_reset(rh);

            rpc_ep_resolve_binding(rh, perfb_v1_0_c_ifspec, &st);
            if (st != rpc_s_ok)
            {
                fprintf(stderr, "*** Can't resolve \"perfb\" interface - %s\n",
                        error_text(st));
                exit(1);
            }

            binding_to_string_binding(rh, &pstring, &st);
            printf("  binding resolved to: %s\n", pstring);
            rpc_string_free(&pstring, &st);
        }

        /*
         * Clear binding to server and make a simple call to the "perfb" interface.
         */
        binding_reset(rh);

        perfb_init(rh, (idl_char *) name);
        printf("  result of forwarded call = \"%s\"\n", name);

        /*
         * Clear binding again and make a call that's too big to fit in a
         * single pkt to make sure multi-pkt forwarding works.  Note that old
         * perf servers don't handle this call so catch that sort of error.
         */
        binding_reset(rh);

        for (i = 0, rsum = 0; i < FSIZE; i++)
        {
            d[i] = i;
            rsum += d[i];
        }

        TRY
        {
            perfb_in(rh, d, FSIZE, true, &sum);
            if (sum != rsum)
            {
                fprintf(stderr, "*** Sum mismatch in large forwarded call (%lu, %lu)\n",
                    sum, rsum);
            }
            else
            {
                printf("  large forwarded call completed OK\n");
            }
        }
        CATCH (rpc_x_op_rng_error)
        {
            printf ("  warning: server doesn't implement \"perfb_in\" procedure ");
            printf ("(probably an old server)\n");
            printf ("           large forwarded call test skipped\n");
        }
        ENDTRY

        if (! compat_mode)
        {
            /*
             * Test forwarded mgmt calls.
             */
            forwarding_mgmt_test (rh, &NilTypeObj, "nil type object");
            forwarding_mgmt_test (rh, &FooObj1, "non-nil type object");
        }

        /*
         * Clear binding again and make a broadcast call.
         */
        binding_reset(rh);

        rpc_binding_set_object(rh, NULL, &st);
        if (st != 0)
        {
            fprintf(stderr, "*** Can't reset object in binding to nil - %s\n",
                error_text(st));
            exit(1);
        }

        TRY
        {
            perfb_brd(rh, result);
            binding_to_string_binding (rh, &name2);
            printf("  broadcast forwarded call completed OK\n");
            printf("    bound to \"%s\", result=\"%s\"\n", name2, result);
        }
        CATCH (rpc_x_invalid_call_opt)
        {
            printf ("  warning: can't do broadcast\n");
        }
        CATCH (rpc_x_op_rng_error)
        {
            printf ("  warning: server doesn't implement \"perfb_brd\" procedure ");
            printf ("(probably an old server)\n");
            printf ("           broadcast call test skipped\n");
        }
        CATCH (rpc_x_comm_failure)
        {
            printf ("  warning: communications failure (may be an old server)\n");
            printf ("           broadcast call test skipped\n");
        }
        CATCH_ALL
        {
            exc_report(THIS_CATCH);
            fprintf (stderr, "*** Unknown exception raised in during broadcast forwarded call\n");
            RERAISE;
        }
        ENDTRY
    }
    FINALLY
    {
        /*
         * Tell server to unregister the "perfb" interface.
         */
        rh = binding_from_string_binding(NULL, argv[2]);

        perf_unregister_b(rh, &st);
        if (st != 0)
        {
            fprintf(stderr, "*** Can't unregister \"perfb\" interface - %s\n",
                error_text(st));
            exit(1);
        }
    }
    ENDTRY
}


More information about the wine-devel mailing list