You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cli-dev@httpd.apache.org by Tonko Juricic <to...@yahoo.com> on 2004/12/10 07:51:31 UTC

Finally works! (was: CLR wants all APR types)

To resolve missing type metadata info I tried the
trick mentioned on: http://www.winterdom.com/mcppfaq/
site.

Basically I had to put the following code in
WorkerRequest.cpp:

namespace Apache {
namespace Native {
extern "C"  
{ 
	struct apr_table_t {};
	struct apr_bucket_alloc_t {};
	struct apr_pool_t {};
}
}
}

mod_aspdotnet.cpp also had to be changed because of
ambiguous apr_pool_t symbol. All apr_pool_t variables
in mod_aspdotnet.cpp were disambiguated by global
scope resolution operator ::apr_pool_t.

The next problem I had was access exception reported
by CLR:

[HttpException (0x80004005): The current identity (NT
AUTHORITY\SYSTEM) does not have write access to
'C:\WINDOWS\Microsoft.NET\Framework\v1.2.30703\Temporary
ASP.NET Files'.]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext
context) +702
  
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext
context) +69
  
System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest
wr) +100

Really, I had no 'Temporary ASP.NET Files' subfolder
on my machine at all. I don't know who creates it - I
guess IIS installation may create it but I had never
run ASP.NET under IIS (nor IIS itself) on this
machine. So I created the folder manually.

And then my .NET Web applications started running just
fine!

Nice!

Tony


		
__________________________________ 
Do you Yahoo!? 
Take Yahoo! Mail with you! Get it on your mobile phone. 
http://mobile.yahoo.com/maildemo 

Re: Finally works! (was: CLR wants all APR types)

Posted by Tonko Juricic <to...@yahoo.com>.
--- Jeff White <jl...@earthlink.net> wrote:

> Isn't .NET 1.2.xxx the ASP.NET 
> 2.0 .NET Framework's beta?

OTOH, beats me where did 1.2 come from. I did quite a
few system upgrades, installed WSE 2.0, WebMatrix,
etc.

Tony


		
__________________________________ 
Do you Yahoo!? 
Jazz up your holiday email with celebrity designs. Learn more. 
http://celebrity.mail.yahoo.com

Re: Finally works! (was: CLR wants all APR types)

Posted by Tonko Juricic <to...@yahoo.com>.
--- Jeff White <jl...@earthlink.net> wrote:

> I'm confused...
> 
> Isn't .NET 1.2.xxx the ASP.NET 
> 2.0 .NET Framework's beta?

I don't think so. I installed Visual C++ 2005 Express
Edition Beta on another machine and got .NET Framevork
v2.0 with it. It is clearly distinct from 1.2 that
came with VS.NET 2003 installed on that same machine.

Machine on which I am testing mod asp has no Framework
2.0.

Tony
Tony

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

Re: Finally works! (was: CLR wants all APR types)

Posted by Jeff White <jl...@earthlink.net>.
From: "William A. Rowe, Jr." 


> Tonko Juricic wrote:

>>
>>Huh? I think I am as confused as is C++ 2003 compiler,
>>trying to explain this to myself!
>>

I'm confused...

Isn't .NET 1.2.xxx the ASP.NET 
2.0 .NET Framework's beta?

And compiling the above with 
the 2003 compiler?

Jeff



Re: Finally works! (was: CLR wants all APR types)

Posted by Tonko Juricic <to...@yahoo.com>.
--- "William A. Rowe, Jr." <wr...@rowe-clan.net>
wrote:

> Can you pinpoint anywhere that we actually reference
> the unmanaged data from managed code (forcing some
> marshalling), or have we successfully kept all of
> the unmanaged data references within the context of
> unmanaged code?

I looked and looked and ... concluded that I am
learning a lot by looking at the optimal way you did
this 'inerfacing' and that problem reported is
probably a compiler bug.

If it were present in earlier runtimes one could be
more lenient and consider it as an 'unpolished
feature', due to pinvoke initially intended for
lanaguages like C#.

I can only notice details like this:

-when there is no dummy apr_table_t compiler generates
pinvokeimpl for apr_table_elts()

-when dummy is present apr_table_elts() is not
generated

-apr_table_setn() is always present as pinvokeimpl,
whether you define dummy or no.

-because apr_table_elts() uses pointer to constant
apr_table_t, compiler is apparently trying to make
some intelligent conclusions about the invocation of
native methods and marshalling if its parameters.   

-exception does not happen in WorkerRequest
constructor where apr_table_elts() is called. So CLR
is not concerned about apr_table_t type at this point,
whether you have its dummy definition or no.

- managed code must make some determination about
types and sizes inside request_rec because it passes
its members to native calls, like in
SetKnownResponseHeader:
....
IL_0065:  ldfld      valuetype
Apache.Native.request_rec*
Apache.Web.WorkerRequest::rr
  IL_006a:  ldc.i4     0xa8
  IL_006f:  add
  IL_0070:  ldind.i4
  IL_0071:  ldloc.3
  IL_0072:  ldloc.0
  IL_0073:  call       void
modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall)
apr_table_setn(valuetype Apache.Native.apr_table_t*,
....

I'm not sure this issue is worthy of spending more
time, except maybe as the preparation for solving
possible troubles in the future.

Tony 

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

Re: Finally works! (was: CLR wants all APR types)

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 07:31 PM 12/10/2004, Tonko Juricic wrote:

>--- "William A. Rowe, Jr." <wr...@rowe-clan.net>
>wrote:
>
>> You realize we missed the turn?
>...
>> So one is left with the question; what is c++ 2003
>> trying to accomplish, anyways?
>
>Huh? I think I am as confused as is C++ 2003 compiler,
>trying to explain this to myself!
>
>This is partly due to (I think) confusing terminology
>or (my) confusing use of terminology.
>
>In particular, terms 'unmanaged' and 'managed', when
>applied to data, can mean data residing in managed or
>unmanaged memory, which then implies marshalling on
>transitions between managed and unmanaged code.
>
>It can also mean that data type is unmanaged, in the
>sense of data type not corresponding directly to any
>of standard CLR types, which again implies marshalling
>in the sense of tranformation between data types.
>
>All in all, I agree with you that:
>
>request_rec __nogc *rr;
>
>clearly does not reside in managed memory so native
>call:
>
>apr_table_setn(rr->headers_out,
>response_headers_c[index], poolval);
>
>is a transition from unmanaged memory to unmanaged
>memory and no marshalling of any sort is needed.
>
>I guess that compiler is not able to determine that
>when it encounters apr_table_setn() prototype.
>
>It may be just a bug, since previous versions caused
>no such issues.
>
>I'm just guessing... probably again confusing myself
>and anybody reading this.

I understood you perfectly :)

Can you pinpoint anywhere that we actually reference the
unmanaged data from managed code (forcing some marshalling),
or have we successfully kept all of the unmanaged data 
references within the context of unmanaged code?

Yes, I'm familiar with the transition issues, and tried
to keep clear boundaries between managed and unmanaged
code and data to avoid excessive marshalling.

Bill



Re: Finally works! (was: CLR wants all APR types)

Posted by Tonko Juricic <to...@yahoo.com>.
--- "William A. Rowe, Jr." <wr...@rowe-clan.net>
wrote:

> You realize we missed the turn?
...
> So one is left with the question; what is c++ 2003
> trying to accomplish, anyways?

Huh? I think I am as confused as is C++ 2003 compiler,
trying to explain this to myself!

This is partly due to (I think) confusing terminology
or (my) confusing use of terminology.

In particular, terms 'unmanaged' and 'managed', when
applied to data, can mean data residing in managed or
unmanaged memory, which then implies marshalling on
transitions between managed and unmanaged code.

It can also mean that data type is unmanaged, in the
sense of data type not corresponding directly to any
of standard CLR types, which again implies marshalling
in the sense of tranformation between data types.

All in all, I agree with you that:

request_rec __nogc *rr;

clearly does not reside in managed memory so native
call:

apr_table_setn(rr->headers_out,
response_headers_c[index], poolval);

is a transition from unmanaged memory to unmanaged
memory and no marshalling of any sort is needed.

I guess that compiler is not able to determine that
when it encounters apr_table_setn() prototype.

It may be just a bug, since previous versions caused
no such issues.

I'm just guessing... probably again confusing myself
and anybody reading this.

Tony




__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

Re: Finally works! (was: CLR wants all APR types)

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 04:00 PM 12/10/2004, Tonko Juricic wrote:

>I don't think structure size can possibly matter
>because, if any marshalling of value type (as
>described in MSDN) was going on here, I can not
>imagine how anything could possibly work.

You realize we missed the turn?

Run ildasm on the distributed binary.  ALL of the code
that accesses our opaque structures is actually native code,
unmanaged.  There [should be] no marshaling.

So one is left with the question; what is c++ 2003 trying to
accomplish, anyways?

Bill



Re: Compiling with VC++ 8 (Express beta)

Posted by Tonko Juricic <to...@yahoo.com>.
--- Jeff White <jl...@earthlink.net> wrote:
 
> Isn't the loading of the CLR 
> "different" for _any_ .NET 
> version over 1.1?
> 
> Hasn't
> CLSID_CorRuntimeHost 
> and 
> IID_ICorRuntimeHost
> been replaced with
> CLSID_CLRRuntimeHost
> and
> IID_ICLRRuntimeHost?
> 
> And aren't there many, many 
> hosting options available for 
> the .NET 1.2 (and up) 
> Framework?
> 
> Plus aren't there major different
> "plain C++ programming styles" 
> changes for version 8 (and so on)?
> 
> No matter what the answers are,
> feel free to branch the .NET 1.1 
> mod_aspdotnet source code 
> and carry on.   ;)

Sorry, but I don't have a slightest idea of what are
you talking about.

I don't see the reason to branch the code. In fact, I
don't think I even have CVS update rights, since I
never asked for nor intended it.

I'm quite happy with being able to compile current
code with only minor modifications, using both VS.NET
2003 and VS Express 2005 compilers, and run it on both
1.x and 2.x runtimes. 

That's about all that I cared about and it is fine
with me for now, considering approaching holidays.

Cheers,
Tony 

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

Re: Compiling with VC++ 8 (Express beta)

Posted by Jeff White <jl...@earthlink.net>.
From: "Tonko Juricic" 

> Subject: Compiling with VC++ 8 (Express beta)


Isn't the loading of the CLR 
"different" for _any_ .NET 
version over 1.1?

Hasn't
CLSID_CorRuntimeHost 
and 
IID_ICorRuntimeHost
been replaced with
CLSID_CLRRuntimeHost
and
IID_ICLRRuntimeHost?

And aren't there many, many 
hosting options available for 
the .NET 1.2 (and up) 
Framework?

Plus aren't there major different
"plain C++ programming styles" 
changes for version 8 (and so on)?

No matter what the answers are,
feel free to branch the .NET 1.1 
mod_aspdotnet source code 
and carry on.   ;)

Jeff



Compiling with VC++ 8 (Express beta)

Posted by Tonko Juricic <to...@yahoo.com>.
Without dummy definitions VC 8 linker gives warnings:

WorkerRequest.obj : warning LNK4248: unresolved
typeref token (01000027) for
'Apache.Native.apr_pool_t'
WorkerRequest.obj : warning LNK4248: unresolved
typeref token (01000029) for
'Apache.Native.apr_bucket_alloc_t'
WorkerRequest.obj : warning LNK4248: unresolved
typeref token (0100002A) for
'Apache.Native.apr_table_t'

and IL code now contains dummy type metadata.

Explanation of this warning is that it occurs when
there is only a forward declaration for a type in an
MSIL module (compiled with /clr), where the type is
referenced in the MSIL module, and where the MSIL
module is linked with a native module that has a
definition for the type.

Bad news is that: 

virtual String __gc * GetUnknownRequestHeaders(void)
__gc[]__gc[]

won't compile, giving error:

System::String __gc * __gc[]' : a managed array cannot
have this element type.

Finally, destructors with void return like:
   void ~Host();
also caused compiler error. 

Tony


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

Re: Finally works! (was: CLR wants all APR types)

Posted by Tonko Juricic <to...@yahoo.com>.
--- "William A. Rowe, Jr." <wr...@rowe-clan.net>
wrote:

> Actually, you declared an empty struct, not an
> opaque one.
> 
> Try
> 
>     struct apr_table_t {
>         char foo[];
>     }
> 
> to declare a structure of indeterminant size.

All that does is cause an extra compiler warning:

warning C4200: nonstandard extension used : zero-sized
array in struct/union
Cannot generate copy-ctor or copy-assignment operator
when UDT contains a zero-sized array

and ILDASM shows that in both cases you get the same
CLI type:

.class public sequential ansi sealed apr_table_t
       extends [mscorlib]System.ValueType
{
  .pack 1
  .size 1
... some attributes deleted
} // end of class apr_table_t

I don't think structure size can possibly matter
because, if any marshalling of value type (as
described in MSDN) was going on here, I can not
imagine how anything could possibly work.

MSDN also mentions that pointers to structures inside
structures with known layout are marshalled as IntPtr.

That seems to be our case with request_rec and,
apparently, compiler gets confused when members of
request_rec (rather than request_rec pointer itself)
are passed as parameters to native functions.

That's my theory anyway.

Tony


		
__________________________________ 
Do you Yahoo!? 
Yahoo! Mail - Find what you need with new enhanced search.
http://info.mail.yahoo.com/mail_250

Re: Finally works! (was: CLR wants all APR types)

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 12:51 AM 12/10/2004, Tonko Juricic wrote:
>To resolve missing type metadata info I tried the
>trick mentioned on: http://www.winterdom.com/mcppfaq/
>site.
>
>Basically I had to put the following code in
>WorkerRequest.cpp:
>
>namespace Apache {
>namespace Native {
>extern "C"  
>{ 
>        struct apr_table_t {};

Actually, you declared an empty struct, not an opaque one.

Try

    struct apr_table_t {
        char foo[];
    }

to declare a structure of indeterminant size.

Bill 


Re: Finally works! (was: CLR wants all APR types)

Posted by Tonko Juricic <to...@yahoo.com>.
--- "William A. Rowe, Jr." <wr...@rowe-clan.net>
wrote:

> That's twisted LOL - glad it works!

Me too but I had doubts and I'm afraid it is
questionable if it will continue to work in never
versions. 

I assume that appearance of this problem indicates
CLR's wish to increase 'management' of data so that,
eventually, it would send a deep copy (all pointers
unrolled) to unmanaged side and then account for the
changes by 'safely' copying them back into 'managed'
CLR types. 

Too bad that OS is full of opaque types (like handles)
so that, ultimately, OS itself would need to be
rewritten ;)

I am looking into warnings like:

'Apache::Web::WorkerRequest::Handler' uses pinning
pointers but unwind semantics are not enabled.
Consider using /EHsc

and 

LINK : warning LNK4243: DLL containing objects
compiled with /clr is not linked with /NOENTRY; image
may not run correctly

but MSDN explanation of causes and fix for the latter
one is not really crystal clear to me. 

Regarding unwind semantics very helpful MC++ FAQ site
says:

"In fact, in VC++ 2005 (aka whidbey), mixing /clr (any
of it's variants) and /EHs will not be possible; the
compiler will require you to especify /EHa instead.
Given this, it is a good time to ensure your
applications are being compiled now with the
appropiate combinations of switches"

Site copyright notice is quite old:
"Copyright(C) 2002, Tomas Restrepo", so I guess this
quotation is legal.

Tony

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

Yet another way....

Posted by Tonko Juricic <to...@yahoo.com>.
.. to fool the compiler (or CLR, or both) is to
created additional unmanaged wrapper methods.

For example, I was able to avoid dummy definition of
apr_table _t:

namespace Apache {
namespace Native {
extern "C"  
{ 
   struct apr_table_t {};
....

by introducing two umanaged functions in
WorkerRequest.cpp like this:

static const apr_array_header_t __nogc *
InternalAprTableElts(request_rec __nogc* rr, int mode)
{
return apr_table_elts(
mode==1?rr->headers_in:rr->subprocess_env);
}

static void InternalAprTableSet(request_rec __nogc
*rr, 
const char __nogc * key,
const char __nogc * val )
{ 
   apr_table_set(rr->headers_out, key, val);
}

This required moving bodies of
SendKnownResponseHeader() and
SendUnknownResponseHeader() from header to cpp file.

This worked but is clearly less efficient and uglier.
The only reason I tried it is because I found CLR
thinking that apr_table_t is value type large 1 byte
(caused by dummy definition) somewhat scary.

I guess that for now we have to rely on the fact that
all apr_table_t pointers inside request_rec are
marshalled as IntPtr.

Tony


		
__________________________________ 
Do you Yahoo!? 
Take Yahoo! Mail with you! Get it on your mobile phone. 
http://mobile.yahoo.com/maildemo 

Re: Finally works! (was: CLR wants all APR types)

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 12:51 AM 12/10/2004, Tonko Juricic wrote:
>To resolve missing type metadata info I tried the
>trick mentioned on: http://www.winterdom.com/mcppfaq/
>site.
>
>Basically I had to put the following code in
>WorkerRequest.cpp:
>
>namespace Apache {
>namespace Native {
>extern "C"  
>{ 
>        struct apr_table_t {};
>        struct apr_bucket_alloc_t {};
>        struct apr_pool_t {};
>}
>}
>}

That's twisted LOL - glad it works!

>mod_aspdotnet.cpp also had to be changed because of
>ambiguous apr_pool_t symbol. All apr_pool_t variables
>in mod_aspdotnet.cpp were disambiguated by global
>scope resolution operator ::apr_pool_t.

Ick.  Gotta be something cleaner.

>The next problem I had was access exception reported
>by CLR:
>
>[HttpException (0x80004005): The current identity (NT
>AUTHORITY\SYSTEM) does not have write access to
>'C:\WINDOWS\Microsoft.NET\Framework\v1.2.30703\Temporary
>ASP.NET Files'.]
>   System.Web.HttpRuntime.FirstRequestInit(HttpContext
>context) +702

That's easy.  Just run Apache as the ASP.NET user in the run-as
part of the service options.

Really need to document that.

Bill