Three bugs deploying COM server

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Three bugs deploying COM server

Chris Uppal-3
Hi,

I've been trying to get the Random Stream COM server example to work as I
thought it should, and have hit a few difficulties that I /think/ are bugs.

First off, deploying the package creates a corandom.dll OK, and that /seems/ to
work OK, but I think it's buggy.  Specifically, trying to unregister it with
    regsvr32 /u corandom.dll
caused a corandom.ERRORS to be created.  I'll append the file, but I think the
problem is because the implementation of SessionManager>>queryEndSession sends
#asValue, but Object>>asValue is in the 'Dolphin Value Models' package which is
not marked as a pre-requisite, and which has therefore been discarded by the
stripper.  I saw several other hard-to-reproduce errors that I now assume were
caused by the same problem.  I suspect that this stripping of #asValue is a
fairly general problem that may affect other deployed applications' session
managers too.

Second, and very trivial, the deployment process leaves a 'corandom.tmp' file
in the target directory.

I was expecting that if I loaded the Random Stream package into my development
image (thus allowing the registration code in the post-install script to run),
that I could then run the RandomVBClient.exe program and have it connect
temporarily to my running image to service the COM requests.  The first problem
was that that consistently attempted to re-load my dev. image in a new Dolphin
session instead of connecting to the existing one.  After reading and
re-reading (and re-reading ;-) just about every post in the archive (well,
that's how it felt), it became clear that I needed to delete the
<classid>\'InProcServer32' entry from the registry, leaving just the
'LocalServer32' entry.   (Which makes perfect sense in retrospect, but I think
it could do to be emphasised in the documentation, even if only in the example
package's comment -- the only in-image comment I could find seemed to imply
that it just wasn't possible to run that way)

However, removing that key didn't fix the problem.  As far as I can see, it's
because

     COMRandomStream revokeClassFactories.

doesn't fully unwind the effects of:

     COMRandomStream register; registerClassFactory.

The problem is that COMClassFactory>>revokeOn: does not remove the server class
from the "Factories" collection.  Hence when you next do
COMClassFactory>>on:[clisid:] the method sees that the server class is already
in the collection and so doesn't "bother" to get the factory re-registered with
Windows.

I hope that all makes sense -- I know virtually nothing of COM, so I may be
misinterpreting...

    -- chris


************************** Dolphin Virtual Machine Dump Report
***************************

14:55:12, 24/01/2005: True does not understand #asValue

*----> VM Context <----*
Process: {00D70004:size 122 words, suspended frame 00D70049, priority 5,
callbacks 0
last failure 0:nil, FPE mask 3, thread nil}
Active Method: AXDllSessionManager>>logError:
IP: 00C82D47 (15)
SP: 00D70298
BP: 00D70270 (139)
ActiveFrame: {00D70274: cf 00D70259, sp 00D70288, bp 00D70270, ip 5,
AXDllSessionManager>>logError:}
 receiver: a AXDllSessionManager
 arg[0]: a MessageNotUnderstood


New Method: VMLibrary>>dump:path:stackDepth:walkbackDepth:
Message Selector: #dump:path:stackDepth:walkbackDepth:

*----> Stack <----*
[00D70298: 149]-->50
[00D70294: 148]-->60
[00D70290: 147]-->nil
[00D7028C: 146]-->'True does not understand #asValue'
[00D70288: 145]-->a VMLibrary
[00D70284: 144]-->7045432
[00D70280: 143]-->AXDllSessionManager>>logError:
[00D7027C: 142]-->7045444
[00D70278: 141]-->8
[00D70274: 140]-->7045420
[00D70270: 139]-->a MessageNotUnderstood
[00D7026C: 138]-->a AXDllSessionManager
[00D70268: 137]-->7045418
[00D70264: 136]-->AXDllSessionManager>>unhandledException:
[00D70260: 135]-->7045428
[00D7025C: 134]-->7
[00D70258: 133]-->7045406
[00D70254: 132]-->a MessageNotUnderstood
[00D70250: 131]-->a AXDllSessionManager
[00D7024C: 130]-->7045404
[00D70248: 129]-->SessionManager>>onUnhandledError:
[00D70244: 128]-->7045414
[00D70240: 127]-->3
[00D7023C: 126]-->7045392
[00D70238: 125]-->a MessageNotUnderstood
[00D70234: 124]-->a AXDllSessionManager
[00D70230: 123]-->7045392
[00D7022C: 122]-->Error>>defaultAction
[00D70228: 121]-->7045400
[00D70224: 120]-->8
...
<88 slots omitted>
...
[00D700C0: 31]-->a MethodContext for: BlockClosure>>ifCurtailed: frame: d700b1
receiver: [] @ 808006 in nil
[00D700BC: 30]-->BlockClosure>>ifCurtailed:
[00D700B8: 29]-->7045220
[00D700B4: 28]-->20
[00D700B0: 27]-->7045198
[00D700AC: 26]-->7045194
[00D700A8: 25]-->BlockClosure>>ensure:
[00D700A4: 24]-->7045206
[00D700A0: 23]-->7
[00D7009C: 22]-->7045182
[00D70098: 21]-->nil
[00D70094: 20]-->[] @ 34 in ExceptionHandlerAbstract>>try:
[00D70090: 19]-->[] @ 15 in ExceptionHandlerAbstract>>try:
[00D7008C: 18]-->a MethodContext for: ExceptionHandlerAbstract>>try: frame:
d7007d receiver: a ExceptionHandler
[00D70088: 17]-->ExceptionHandlerAbstract>>try:
[00D70084: 16]-->7045190
[00D70080: 15]-->42
[00D7007C: 14]-->7045172
[00D70078: 13]-->7045168
[00D70074: 12]-->BlockClosure>>on:do:
[00D70070: 11]-->7045180
[00D7006C: 10]-->10
[00D70068: 9]-->7045156
[00D70064: 8]-->[] @ 12 in BlockClosure>>newProcess
[00D70060: 7]-->ProcessTermination
[00D7005C: 6]-->[] @ 8 in InputState>>forkMain
[00D70058: 5]-->[] @ 6 in BlockClosure>>newProcess
[00D70054: 4]-->BlockClosure>>newProcess
[00D70050: 3]-->7045164
[00D7004C: 2]-->20
[00D70048: 1]-->0
<Bottom of stack>

*----> Stack Back Trace <----*
{00D70274: cf 00D70259, sp 00D70288, bp 00D70270, ip 5,
AXDllSessionManager>>logError:}
 receiver: a AXDllSessionManager
 arg[0]: a MessageNotUnderstood

{00D70258: cf 00D7023D, sp 00D70268, bp 00D70254, ip 4,
AXDllSessionManager>>unhandledException:}
 receiver: a AXDllSessionManager
 arg[0]: a MessageNotUnderstood

{00D7023C: cf 00D70221, sp 00D7024C, bp 00D70238, ip 4,
AXDllSessionManager(SessionManager)>>onUnhandledError:}
 receiver: a AXDllSessionManager
 arg[0]: a MessageNotUnderstood

{00D70220: cf 00D70209, sp 00D70230, bp 00D70220, ip 5,
MessageNotUnderstood(Error)>>defaultAction}
 receiver: a MessageNotUnderstood

{00D70208: cf 00D701F5, sp 00D70218, bp 00C7ADD8, ip 57,
MessageNotUnderstood(Exception)>>_propagateFrom:}
 receiver: a MessageNotUnderstood
 arg[0]: a ExceptionHandler
 temp[0]: nil
 temp[1]: a ExceptionHandler
 temp[2]: nil
 temp[3]: a Process('Main' base 00D70000 [ACTIVE] in
AXDllSessionManager>>logError: sp=00000000 ip=8 list=nil)
 temp[4]: nil

{00D701F4: cf 00D701D9, sp 00D70204, bp 00D701F0, ip 6,
MessageNotUnderstood(Exception)>>_propagate}
 receiver: a MessageNotUnderstood
 temp[0]: nil

{00D701D8: cf 00D701C1, sp 00D701E8, bp 00D701D8, ip 12,
MessageNotUnderstood(Exception)>>signal}
 receiver: a MessageNotUnderstood

{00D701C0: cf 00D701A1, sp 00D701D0, bp 00D701B8, ip 13, MessageNotUnderstood
class>>receiver:message:}
 receiver: MessageNotUnderstood
 arg[0]: true
 arg[1]: Message selector: #asValue arguments: a Array

{00D701A0: cf 00D70185, sp 00D701B0, bp 00D7019C, ip 5,
True(Object)>>doesNotUnderstand:}
 receiver: true
 arg[0]: Message selector: #asValue arguments: a Array

{00D70184: cf 00D70169, sp 00D70194, bp 00D70180, ip 3,
AXDllSessionManager(SessionManager)>>queryEndSession}
 receiver: a AXDllSessionManager
 temp[0]: nil

{00D70168: cf 00D7014D, sp 00D70178, bp 00D70164, ip 3,
AXDllSessionManager(SessionManager)>>onQuit:}
 receiver: a AXDllSessionManager
 arg[0]: -1

{00D7014C: cf 00D70131, sp 00D7015C, bp 00D70148, ip 16,
InputState>>pumpMessage:}
 receiver: a InputState
 arg[0]: a MSG

{00D70130: cf 00D70109, sp 00D70140, bp 00D70120, ip 22,
InputState>>loopWhile:}
 receiver: a InputState
 arg[0]: [] @ 6 in InputState>>mainLoop
 temp[0]: a MSG
 temp[1]: true
 temp[2]: nil

{00D70108: cf 00D700F5, sp 00D70118, bp 00C7ADA0, ip 12, InputState>>mainLoop}
 receiver: a InputState

{00D700F4: cf 00D700E1, sp 00D70104, bp 00C7AC18, ip 13, [] in
InputState>>forkMain}
 receiver: a InputState

{00D700E0: cf 00D700CD, sp 00D700F0, bp 00C7AD68, ip 11,
ExceptionHandler(ExceptionHandlerAbstract)>>markAndTry}
 receiver: a ExceptionHandler
 temp[0]: nil

{00D700CC: cf 00D700B1, sp 00D700DC, bp 00C7ACF8, ip 21, [] in
ExceptionHandler(ExceptionHandlerAbstract)>>try:}
 receiver: a ExceptionHandler
 arg[0]: [] @ 8 in InputState>>forkMain
 temp[0]: nil
 temp[1]: nil
 temp[2]: a Process('Main' base 00D70000 [ACTIVE] in
AXDllSessionManager>>logError: sp=00000000 ip=8 list=nil)

{00D700B0: cf 00D7009D, sp 00D700C8, bp 00C7AD30, ip 17,
BlockClosure>>ifCurtailed:}
 receiver: [] @ 8421382 in nil
 arg[0]: [] @ 34 in ExceptionHandlerAbstract>>try:
 temp[0]: nil
 temp[1]: nil
 temp[2]: nil

{00D7009C: cf 00D7007D, sp 00D700AC, bp 00D70094, ip 4, BlockClosure>>ensure:}
 receiver: [] @ 15 in ExceptionHandlerAbstract>>try:
 arg[0]: [] @ 34 in ExceptionHandlerAbstract>>try:
 temp[0]: nil

{00D7007C: cf 00D70069, sp 00D7008C, bp 00C7ACF8, ip 39,
ExceptionHandler(ExceptionHandlerAbstract)>>try:}
 receiver: a ExceptionHandler
 arg[0]: [] @ 8 in InputState>>forkMain
 temp[0]: nil
 temp[1]: nil
 temp[2]: a Process('Main' base 00D70000 [ACTIVE] in
AXDllSessionManager>>logError: sp=00000000 ip=8 list=nil)

{00D70068: cf 00D70049, sp 00D70078, bp 00D70060, ip 7, BlockClosure>>on:do:}
 receiver: [] @ 8 in InputState>>forkMain
 arg[0]: ProcessTermination
 arg[1]: [] @ 12 in BlockClosure>>newProcess

{00D70048: cf 00000001, sp 00D70058, bp 00C7AC88, ip 17, [] in
BlockClosure>>newProcess}
 receiver: [] @ 8 in InputState>>forkMain
 temp[0]: nil

<Bottom of stack>

***** End of dump *****


Reply | Threaded
Open this post in threaded view
|

Re: Three bugs deploying COM server

Blair McGlashan-3
"Chris Uppal" <[hidden email]> wrote in message
news:[hidden email]...
> Hi,
>
> I've been trying to get the Random Stream COM server example to work as I
> thought it should, and have hit a few difficulties that I /think/ are
> bugs.
>

Thanks Chris. The sample has aged somewhat since it was last looked at in
earnest.

> First off, deploying the package creates a corandom.dll OK, and that
> /seems/ to
> work OK, but I think it's buggy.  Specifically, trying to unregister it
> with
>    regsvr32 /u corandom.dll
> caused a corandom.ERRORS to be created.  I'll append the file, but I think
> the
> problem is because the implementation of SessionManager>>queryEndSession
> sends
> #asValue, but Object>>asValue is in the 'Dolphin Value Models' package
> which is
> not marked as a pre-requisite, and which has therefore been discarded by
> the
> stripper.  I saw several other hard-to-reproduce errors that I now assume
> were
> caused by the same problem.  I suspect that this stripping of #asValue is
> a
> fairly general problem that may affect other deployed applications'
> session
> managers too.

Thanks. This is a known issue for which there is a beta patch:

http://object-arts.com/Lib/Update/Dolphin/5.1/1545.st

>
> Second, and very trivial, the deployment process leaves a 'corandom.tmp'
> file
> in the target directory.

This is deliberate. Its a copy of the stripped image file for debugging
purposes. If you don't want it override/modify/delete
AXDllImageStripper>>keepImageFile.

>
> I was expecting that if I loaded the Random Stream package into my
> development
> image (thus allowing the registration code in the post-install script to
> run),
> that I could then run the RandomVBClient.exe program and have it connect
> temporarily to my running image to service the COM requests.  The first
> problem
> was that that consistently attempted to re-load my dev. image in a new
> Dolphin
> session instead of connecting to the existing one.  After reading and
> re-reading (and re-reading ;-) just about every post in the archive (well,
> that's how it felt), it became clear that I needed to delete the
> <classid>\'InProcServer32' entry from the registry, leaving just the
> 'LocalServer32' entry.   (Which makes perfect sense in retrospect, but I
> think
> it could do to be emphasised in the documentation, even if only in the
> example
> package's comment -- the only in-image comment I could find seemed to
> imply
> that it just wasn't possible to run that way)

There is a draft document which covers this subject in quite some detail. It
is available for download from:

http://object-arts.com/Lib/Downloads/Misc/DevelopingCOMComponents.pdf

See the "Testing & Debugging" section. Any feedback would be welcome.

>
> However, removing that key didn't fix the problem.  As far as I can see,
> it's
> because
>
>     COMRandomStream revokeClassFactories.
>
> doesn't fully unwind the effects of:
>
>     COMRandomStream register; registerClassFactory.
>

It's not intended to. COMInterfaceImp>>unregister and
#unregisterClassFactory are the respective complements.

>...

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Three bugs deploying COM server

Chris Uppal-3
Blair

> There is a draft document which covers this subject in quite some detail.
> It is available for download from:
>
> http://object-arts.com/Lib/Downloads/Misc/DevelopingCOMComponents.pdf
>
> See the "Testing & Debugging" section. Any feedback would be welcome.

Thanks for he link.  I'm sorry not to have replied before, but I wanted to wait
until I had spent some time actually applying the information in the COM guide
before commenting. Unfortunately that hasn't happened, but here are a few
comments anyway...

I found it a good, clear, and helpful guide in general, but there are one or
two things that I think would be worth improving.

The first is that -- at least for me -- it was organised backwards.  The
startup sequences -- which explain the /architecture/ and are fundamental to
understanding -- right at the end; whereas the nitpicking about understanding
COM ref-counting (which I'd hope I /don't/ need to understand for simple cases)
was right at the beginning.  (BTW, the IPDolphin.DLL could probably do with a
bit more introduction, something to say that its part of the Dolphin
distribution and lives in the installation directory -- or wherever it does
live).

Secondly I was never very clear on which uses of the word "register" meant
"create an entry in the registry" and which meant to "register with Windows" --
CoRegisterClassObject() or similar (I have the same problem with the code too).

Lastly, the document seems to focus on the wrong three out of four cases.  The
most important case is where I need to understand the architecture for "normal"
deployment -- obviously -- and that's covered well.  The next most important
case (I'd have thought) was when you want to develop/debug by having an
external COM client connect to a /running/ Dolphin image -- that doesn't seem
to be covered at all well (and isn't well-supported by the code either, as far
as I can tell), yet that's exactly what I'd expect to be able to do.  And that
is certainly the way I /want/ to work (why use Dolphin otherwise ? ;-)  The
case that I /don't/ want to hear about (because I don't want to be forced to
work this way) is for the client COM code to cause a new Dolphin image to start
up, yet that case that is covered in detail.  The last case is when the
client and server code are both in the same image, and that's explained well,
but isn't very interesting since, well, I'd expect Smalltalk code to be able to
call Smalltalk code... (Yes, I do realise that it's going through some of the
COM machinery on the way, but that doesn't really persuade me that my COM
component won't turn out to have trivial or fundamental flaws in a more
realistic setting).

Anyway those are the general comments.  The rest of this is from the POV of
someone who knows a /little/ bit about COM (I've read Rogerson), but not done
any COM programming outside Dolphin.  Dolphin seems like a much better
environment to start in -- even though I have no great objection to programming
'C'.  I don't know whether you feel that its fair to hope to start with COM
using just that background plus your guide, but that's the position I was in.

 From that POV, I think that a couple of basics could have done with a little
more explanation.  A 1-paragraph summary/reminder of what a CoClass is, for
instance.  I don't mean a complete rundown of COM, but an overview of the
important players in the COM architecture as it applies to Dolphin (in deployed
or debug modes).  Some of that is there in the later parts of the guide, but I
think it would help to bring it forward in the presentation.

Another thing that would be worth adding to the guide is a quick example of
client code.  I was in the unfortunate position that the tutorial example
didn't work for me, and I was trying to see what was going wrong when Dolphin
wouldn't hang around to be debugged, and the only client I had was the VB
application that I couldn't load into VS2003 (maybe I should have been able
to -- I've never touched VB before).  It would help, I think, if the guide
included a small VBScript or JScript program using the Random example, which
could act as a standalone example of client code.

And, about trying to get the example to work:

> > However, removing that key didn't fix the problem.  As far as I can see,
> > it's
> > because
> >
> >     COMRandomStream revokeClassFactories.
> >
> > doesn't fully unwind the effects of:
> >
> >     COMRandomStream register; registerClassFactory.
> >
>
> It's not intended to. COMInterfaceImp>>unregister and
> #unregisterClassFactory are the respective complements.

Fair enough, but I think that either the unload script should completely clear
up after itself, or it should warn that it doesn't, or you should not refer to
the scripts as an example of how to do things.  I was trying to make stuff work
without properly understanding what I was doing (that was /why/ I was trying to
make stuff work -- so I could learn from the working system !), so not having a
way to return to a clean position made that very difficult (took me all day).
I think that's a problem with the Random example.  If I'm understanding it
correctly, a clean Dolphin image is in a state (w.r.t the COM example) that one
can never return to without changing stuff by hand.  The CoClass is registered
with Windows, but nothing is in the registry.  If you unload the sample package
when you first install Dolphin (as I always do) and then load it again when you
want to play with it, then stuff gets written to the registry.  Also the only
way of getting the class factories registered again (before you have a
reasonable understanding of how this stuff works) is to unload the package and
re-load it.  That, again, doesn't return you to the state you were in with a
clean install.  Also it's unexpected that executing the unload script followed
by the load script (without unloading the package) puts the system into a state
where it /can't/ work (without more cleanup by hand).

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Three bugs deploying COM server

Blair McGlashan-3
Chris

You wrote in message news:4211f0a1$0$38038$[hidden email]...

> Blair
>
>> There is a draft document which covers this subject in quite some detail.
>> It is available for download from:
>>
>> http://object-arts.com/Lib/Downloads/Misc/DevelopingCOMComponents.pdf
>>
>> See the "Testing & Debugging" section. Any feedback would be welcome.
>
> Thanks for he link.  I'm sorry not to have replied before, but I wanted to
> wait
> until I had spent some time actually applying the information in the COM
> guide
> before commenting. Unfortunately that hasn't happened, but here are a few
> comments anyway...
>

Thanks for your detailed and constructive comments. These will be taken into
account when we are revising the document for release.

I agree, BTW, that the scripts associated with the Random stream sample
package are probably not doing the right things. We'll look at that as well.

Regards

Blair