Permission denied creating Singleton in GLOBAL.ASA

T

Tony Proctor

I need to create a process Singleton object for an ASP application, but I'm
having some odd issues

In my GLOBAL.ASA, I have an <OBJECT> element specifying the relevant ProgID
with RUNAT=Server and SCOPE=Application

However, although this works fine for some classes, I get a permission
denied error for classes from a particular DLL. The error response is:-

Active Server Pages error '8002802b'
Create object failed
?
An error occurred while creating object 'oTest'.
Microsoft VBScript runtime error '800a0046'
Permission denied: 'oTest'
/test/utilities/test.asp, line 11

Apart from all the failing classes being in one of two particular DLLs, I
can't see what the pattern is. All the DLLs (working and non-working are
written in VB6)

Can anyone see a possible cause?

Tony Proctor
 
S

Schmidt

Newsbeitrag
Hi Toni,

have you seen (and tested) my Shared-Memory-Example
wich I've posted yesterday?
Works very well across the IIS-STAs with
very good performance (no marshaling involved).
To wrap the approach in a way, that it works
(with a binary chop) somehow like a dictionary
should be no problem - you will end up with
a lean Dictionary-Connector-Class, wich works
against a shared Memory-Store, independent
in wich STA this Class would be instantiated.

Regarding your global.asa-question I have no idea.
From my tests yesterday I've at least found, that
it is somehow important to stop the service using:
net stop iisadmin /y
before any change in the "Dll-Environment".
and to start it after that using:
net start w3svc

Stopping and (re)starting in the server-manager was
somehow not sufficient.

But that one you probably already know.

Olaf
 
T

Tony Proctor

I did see your example Olaf but it wasn't really applicable for what I need.
I actually have a VB class that stores multiple Dictionary objects in an
array - one per "resource" being cached. Each Dictionary could have 20k-30k
items in it. Hence, the problem with memory usage, and why I need a hashed
lookup rather than a binary chop. It's that encapsulating VB class that I
really want as a singleton.

I can't directly add a VB object to the Application collection, but I can if
it was created via the <OBJECT> element in GLOBAL.ASA....or so the theory
goes. Interestingly, the two DLLs it fails with are physically under the
virtual root of the web application. All the ones that work are located
outside of that directory tree. Also, if I specify a similar class from a
different version of the DLL (e.g. MyProj32.ClassName where MyProj32 is
under a different virtual root) then it works without error too

Nothing appears in the event log, and it works if the DLL is running in the
IDE.

Tony Proctor
 
S

Schmidt

I did see your example Olaf but it wasn't really applicable
for what I need.
I'd say, that you could adapt the approach very easy
to your problem.
I actually have a VB class that stores multiple Dictionary
objects in an array - one per "resource" being cached.
Each Dictionary could have 20k-30k items in it.
That's also no problem, since you could hold separate
Arrays (as much as you want) for each resource.
I assume, your current Dictionaries store simple
StringKey<->SingleValue-Pairs for each resource
(accessing each Value over the hashed StringKey).
You can do exactly the same with my approach, and
you could even store StringKey<->MutipleRecordValues
without any problems as long as the RecordValues
only contain simple Types (Strings, Longs, Doubles, etc.).
Hence, the problem with memory usage, and why I need
a hashed lookup rather than a binary chop.
The binary chop was meant to work on the (sorted)
StringKeys of each "Record-Entry" and if implemented
right, retrieving Values by Key or a check for KeyExists
is processed at the same speedlevel as the hashed lookup
of the MS-ScriptingDictionary or the VB-Collection.
In fact the keyed-access would be *much* faster in your
special case, than working against a *marshaled* singleton-
object, because of the non-existent OLE-Call-overhead.

If you work readonly against your Resource-Caches,
you wouldn't even need to implement CriticalSection-
based locking with this approach.
In the current example there is also an defined entry-
point for the STA, wich is the first user of the shared
cache - at this point you could fill all your data into
each of the Resource-Caches.

But I understand, that you want to avoid coding-effort
and that reusing your already existing Resource-Cache-
Class as a singleton would be the easiest way (if you
manage, to get proper singleton-instancing in global.asa).

Just let me know, when the marshaled singleton-approach
doesn't work as you imagine - would enhance the example
then with "multiple Resource-Caching-capabilities" + some
appropriate KeyExists and GetRecordByKey-Methods
for the multiple Resource-Caches.

Olaf
 
A

Anthony Jones

Tony Proctor said:
I need to create a process Singleton object for an ASP application, but I'm
having some odd issues

In my GLOBAL.ASA, I have an <OBJECT> element specifying the relevant ProgID
with RUNAT=Server and SCOPE=Application

However, although this works fine for some classes, I get a permission
denied error for classes from a particular DLL. The error response is:-

Active Server Pages error '8002802b'
Create object failed
?
An error occurred while creating object 'oTest'.
Microsoft VBScript runtime error '800a0046'
Permission denied: 'oTest'
/test/utilities/test.asp, line 11

Apart from all the failing classes being in one of two particular DLLs, I
can't see what the pattern is. All the DLLs (working and non-working are
written in VB6)

Can anyone see a possible cause?

Have you confirmed that a simple CreateObject in a test.asp works for the
class?
Have you checked the access control on the dll (IOW could this genuinely be
a permission denied)?
What isolation level are you using?

Is this at all a sane thing to do anyway? If the object is in an STA what
actually gets stored in application object?
 
T

Tony Proctor

I'm using "High" isolation (this is currently under IIS5 on a W2K box)

I can confirm that a 'New' operator and a CreateObject call both work from
an ASP script. Also, if I instantiate the objects with Session scope via
GLOBAL.ASA then it works. It only seems to fail like this with Application
scope. I've also tried specifying CLASSID= instead of PROGID= in the
GLOBAL.ASA but the results were the same.

The rationale for this is that I need a "singleton" object. I don't care how
I achieve this but it must be callable from any other ASP thread. The
cross-thread calls are a necessary penalty since that singleton will use a
considerable amount of VM for a global cache. I cannot afford to have that
duplicated in every apartment.

Tony Proctor
 
A

Anthony Jones

Tony Proctor said:
I'm using "High" isolation (this is currently under IIS5 on a W2K box)

I can confirm that a 'New' operator and a CreateObject call both work from
an ASP script. Also, if I instantiate the objects with Session scope via
GLOBAL.ASA then it works. It only seems to fail like this with Application
scope. I've also tried specifying CLASSID= instead of PROGID= in the
GLOBAL.ASA but the results were the same.

The rationale for this is that I need a "singleton" object. I don't care how
I achieve this but it must be callable from any other ASP thread. The
cross-thread calls are a necessary penalty since that singleton will use a
considerable amount of VM for a global cache. I cannot afford to have that
duplicated in every apartment.


In an early post you I think you said that you have other classes built with
VB that you were able to successfully create with an object tag with an
application scope? Can you confirm that is so? Normally any attempt to
assign an object in an STA into the application object would fail.

I think Schmidt was directing you to a more complex but more scalable
solution. What happens when the thread on which the object was created is
currently busy processing an ASP script which potentially may take some
time?

Have you checked the permissions on the DLL and anything the class
initialise may need to access. Ensure that such resources allow
IWAM_<machinename> and IUSR_<machinename> appropriate access.
 
T

Tony Proctor

The DLLs are already part of a working application. It's true that you
cannot directly assign an apartment-threaded object into the Application
variables (you get an error) but you can create such an object with
SCOPE=Application via the <OBJECT> tag in GLOBAL.ASA

I can create objects with SCOPE=Application from other DLLs, and - once
created - I can even add them to the Application collection. However, the
DLLs I really want are located under the virtual root of the application,
and they fail as indicated. Oddly, I can do this with classes from a
different version of the same application, from a physically separate
directory, but that's of no practical use.

The code for this class already exists, although it's not used as a
singleton yet. It would be a huge task to re-write it to use shared memory
and mutexes as it currently uses objects

Tony Proctor
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,710
Latest member
bernietqt

Latest Threads

Top