Toon posts:

[C++/ATL/ISAPI] Probleem met eigen ISAPI dll

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben bezig een ISAPI dll te ontwikkelen, zodat ik files uit een database kan halen door middel van 'http://mijn.url.tld/Fetch.dll?naam.txt'.

Om dit voor elkaar te krijgen heb ik met visual studio .net een ATL server project aangemaakt en de volgende instellingen gekozen:
- Generate combined dll
- Geen stencil support

Visual studio gaat dan druk aan de slag en vertelt me dat ik in 'HTTP_CODE ValidateAndExchange()' mijn eigen code moet toevoegen.
De body van die functie heb ik als volgt ingevuld:
code:
1
2
m_HttpResponse.SetContentType("text/html");
m_HttpResponse <<"Worked.";


IIS is geconfigureerd om aanvragen naar '.dll' af te handelen via mijn 'Fetch.dll'. Als ik nu een IE opstart en de url 'http://mijn.url.tld/Fetch.dll?naam.txt' invoer krijg ik dan ook de tekst 'worked' te zien in mijn browser. Fantastisch! :)

Het probleem echter treedt op bij het afsluiten van IIS. Zodra ik via het services control panel IIS afsluit krijg ik de melding 'The service terminated unexpectedly' en in de event viewer wordt de tekst

The World Wide Web Publishing Service service terminated unexpectedly. It has done this 5 time(s). The following corrective action will be taken in 0 milliseconds: No action.

gelogd.
Kennelijk crashed IIS op een of andere manier tijdens of na het uitvoeren van mijn ISAPI dll, maar ik krijg geen enkele foutmelding of wat dan ook tussendoor. Telkens wanneer ik de pagina reload wordt het tellertje hoger, dus er kan ook staan 'has done this 42 times'.

Ik heb me rotgezocht op internet maar kan nergens een vergelijkbaar probleem vinden. Ben ik tegen een bug in 't ATL gebeuren of IIS angelopen of doe ik gewoon iets fout? Wie weet er meer?

Verwijderd

Ik heb nog niet met ATL binnen .Net gewerkt. maar ik kan me voorstellen dat je een interface als IHttpHandler gebruikt. In deze interface zit een isReusable property. Als je hier true aan teruggeeft dan zal deze in memory blijven. Als je in je ISAPI ook nog eens diverse objecten gebruikt dan kan ik me voorstellen dat deze geopend blijven in een proces waar ze niet uit kunnen komen wat dan die foutmelding genereert. Ikzelf maak geen gebruik van ActiveX Template Libraries maar van een simpele class die de IHttpHandler implementeert en kom bovenstaande foutmelding niet tegen. Ik ben dus een beetje aan het gissen...

Misschien iets meer code laten zien van jouw ISAPI implementatie en dan met name de constructor, destructor en interface implementatie.

CJ

Verwijderd

Topicstarter
Er is heel weinig om te laten zien. Het hele geval bestaat momenteel uit een grote berg wizard-gegenereerde code en het enige wat ik er aan heb veranderd is het toevoegen van wat output zodat ik ook kan zien of e.e.a. werkt.

Ik ben er trouwens wel achter inmiddels dat IIS niet altijd omvalt, maar wel 'meestal'. Voor een door een wizard gegenereerd project vind ik dit vreemd en ik weet nu niet echt hoe ik verder moet. (Behalve dan of hier de gouden tip tegenkomen of een andere aanpak gaan kiezen... Het meest frustrerende vind ik dat ik dit zo moeilijk kan debuggen... als ik nou gewoon een access violation zou krijgen ofzo, ipv een proces wat gewoon in stilte afsluit...)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 11:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

waarschijnlijk vangt IIS de error zelf af (om m vervolgens in de event viewer te zetten zeg maar). Maar wat als je het IIS proces debug'd? Misschien kun je dan wel zien waar het fout gaat

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Ik heb al geprobeerd VS.Net er aan te hangen om het boeltje te debuggen, maar dat heeft me weinig opgeleverd. Zodra ik de debugger er aan heb hangen zijn de 'this process terminated unexpectedly' meldingen namelijk verdwenen...
Het lijkt er op dat er ergens een stukje ongeinitialiseerd geheugen wordt gebruikt ofzo, maar dat moet ergens in de framework code zijn (denk ik). Ik ga nu mijn IIS instellingen eens helemaal opschonen (heb er nog meer filters en ISAPI's in hangen) en kijken of ik er een patroon in kan ontdekken...

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 11:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

en krijg je die error ook bij de debug build van je dll?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Debuggen kan wel maar gebruik dan de debug opties binnen je project properties (ga naar URL etc.)

Verwijderd

Topicstarter
Ok dan... ik heb me even vermaakt met windbg en inetinfo.exe en heb een stack dump. Echter... ik snap (nog) weinig van IIS en COM, dus ik weet niet heel goed wat ik er mee aan moet. Als ik zo naar de dump kijk kom ik tot de conclusie dat er iets met COM mis aan 't gaan is bij het unloaden van het een en ander, maar ik ben hier niet zeker van. Ik krijg geen crash adres in mijn DLL, maar zonder mijn rommel lijkt IIS dit niet te doen, dus...

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Microsoft (R) Windows Debugger  Version 6.0.0017.0
Copyright (c) Microsoft Corporation. All rights reserved.

*** wait with pending attach
Symbol search path is: *** Invalid *** : Verify _NT_SYMBOL_PATH setting

0:018> .sympath c:\winnt\symbols
Symbol search path is: c:\winnt\symbols

0:018> .reload
Reloading current modules
......................................................................................

0:018> g
A(1780): Spy filter DLL: HttpFilterProc: SF_NOTIFY_READ_RAW_DATA
A(1780): Filter DLL: HttpFilterProc: SF_NOTIFY_PREPROC_HEADERS
A(1780): CExtension::NotifyPreprocHeaders: Detected request to a path.
ModLoad: 1f430000 1f4a7000   C:\Program Files\Common Files\System\ADO\msado15.dll
.

[And then I open the services control panel and stop the World Wide Web Publishing service]

.
(7c0.7d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=028f1e90 ebx=00000000 ecx=00000000 edx=77b33608 esi=00b8f580 edi=00160b94
eip=77a82aec esp=00b8f56c ebp=00b8f5a4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00010206
ole32!CStdMarshal::DisconnectSrvIPIDs+a5:
77a82aec 8b08             mov     ecx,[eax]         ds:0023:028f1e90=????????

0:004> kb
ChildEBP RetAddr  Args to Child              
00b8f5a4 77a82826 00000001 00160b90 00160b94 ole32!CStdMarshal::DisconnectSrvIPIDs+0xa5
00b8f5d0 77a54b7c 00000001 00000000 77a9dd1a ole32!CStdMarshal::Disconnect+0x19c
00b8f5dc 77a9dd1a 00000000 00b8f640 00b8f7fc ole32!CStdMarshal::HandlePendingDisconnect+0x44
00b8f62c 77a9dbc9 00000001 02675b20 00000001 ole32!CRemoteUnknown::RemReleaseWorker+0x1ba
00b8f63c 77d339c0 00161df0 00000001 02675b20 ole32!CRemoteUnknown::RemRelease+0x13
00b8f65c 77d93570 77a9dbb6 00b8f800 00000003 RPCRT4!Invoke+0x30
00b8fa54 77d949ac 02680348 0016f688 001066e0 RPCRT4!NdrStubCall2+0x63d
00b8fab8 77b29e7f 02680348 001066e0 0016f688 RPCRT4!CStdStubBuffer_Invoke+0xec
00b8fafc 77b29d6e 001066e0 00082e8c 00000000 ole32!SyncStubInvoke+0x61
00b8fb44 77aa7ae7 001066e0 001666e8 02680348 ole32!StubInvoke+0xa8
00b8fba8 77aa7a33 0016f688 00000000 02680348 ole32!CCtxComChnl::ContextInvoke+0xbb
00b8fbc4 77b29c89 001066e0 00000001 02680348 ole32!MTAInvoke+0x18
00b8fbf4 77b29a89 00106698 0016f688 02680348 ole32!AppInvoke+0xb5
00b8fcb4 77b2a12c 02675b18 00000000 00082e70 ole32!ComInvokeWithLockAndIPID+0x29e
00b8fcf4 77d33721 00106698 00082e70 02683240 ole32!ThreadInvoke+0x1b7
00b8fd2c 77d33667 77b29f7b 02683240 00b8fe0c RPCRT4!DispatchToStubInC+0x84
00b8fd84 77d33579 00000000 00000000 00b8fe0c RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x100
00b8fda4 77d48e81 02683240 00000000 00b8fe0c RPCRT4!RPC_INTERFACE::DispatchToStub+0x5e
00b8fdd4 77d34bc6 02683240 02683204 00000000 RPCRT4!RPC_INTERFACE::DispatchToStubWithObject+0xa9
00b8fe10 77d346c5 02683008 00080af8 80030001 RPCRT4!LRPC_SCALL::DealWithRequestMessage+0x1c6
00b8fe28 77d422ff 02683148 00b8fe50 02683008 RPCRT4!LRPC_ADDRESS::DealWithLRPCRequest+0x10c
00b8ff74 77d420d9 77d425b9 00080af8 005aee30 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0x1eb
00b8ff78 77d425b9 00080af8 005aee30 003a0043 RPCRT4!RecvLotsaCallsWrapper+0x9
00b8ffa8 77d424da 0007bff0 00b8ffec 77e887dd RPCRT4!BaseCachedThreadRoutine+0x11f
00b8ffb4 77e887dd 00080c48 005aee30 003a0043 RPCRT4!ThreadStartRoutine+0x18
00b8ffec 00000000 77d424c2 00080c48 00000000 KERNEL32!BaseThreadStart+0x52

Heeft iemand dit eerder gezien? Kan je me dan een hint geven in welke richting ik moet gaan zoeken!?

Verwijderd

Topicstarter
.oisyn schreef op 16 oktober 2002 @ 15:10:
en krijg je die error ook bij de debug build van je dll?
Ja. Ik werk voorlopig alleen met debug builds. Voor de volledigheid heb ik wel een release build getest, maar dat lijkt ook niet te werken...

Verwijderd

Topicstarter
Ok... misschien ben ik er uit. Behalve mijn ISAPI DLL had ik ook nog een ISAPI filter DLL gebouwd die wat database queries uitvoert als de URL aan bepaalde criteria voldoet. Ik heb daarin nu het een en ander veranderd en heb sindsdien geen crashes meer gehad. Eens zien of dat zo blijft :)

Verwijderd

Topicstarter
Hm. Ik ben er dus niet uit :( . Ik ben wel dichter bij het lokaliseren van het probleem, en vermoed nog steeds dat het iets te maken heeft met de database queries en de bijbehorende objecten. Wat is de juiste procedure om een database query te doen vanuit een ISAPI filter? Ik heb nu de volgende code (ranzige code, ik weet het. Moet het nog opschonen):

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
char *CExtension::TranslateURL(const char *pURL, CStringA &strConn)
{
    // COM is initialized already
    char *pReturn = NULL;
    CStringA strURL = pURL;
    CStringA strDirectory;
    CStringA strResource;

    int nPos = -1;
    int nFind;
    
    // Find the last '/'
    while ((nFind = strURL.Find('/', nPos + 1)) != -1) nPos = nFind;

    strDirectory = strURL.Left(nPos);
    strResource = strURL.Right(strURL.GetLength() - (nPos + 1));

    if (strDirectory.GetLength() > 0 && strResource.GetLength() > 0)
    {
        // Both appear to be valid. Let's query the database...
        // TODO: Make strings SQL safe!!!

        // Connection string...
        _bstr_t strCnn = strConn; 

        // Define ADO object pointers.
        // Initialize pointers on define.
        // These are in the ADODB::  namespace.
        _ConnectionPtr pConnection = NULL;

        _bstr_t strFolderID = "";
        _bstr_t strTargetResource = "";

        try
        {
            // Open connection.
            TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
            pConnection->Open (strCnn, "", "", adConnectUnspecified);

            _variant_t rsAffected;
            _RecordsetPtr spRS;

            _bstr_t Query = "SELECT id FROM folders WHERE fullpath = '";
            Query += (const char *)strDirectory;
            Query += "';";

            spRS = pConnection->Execute(Query, &rsAffected, adCmdText);

            if (VARIANT_FALSE == spRS->EndOfFile)
            {
                // Did we get a result?
                FieldsPtr pFields = NULL;
                pFields = spRS->GetFields();
                _variant_t vtIndex; vtIndex.vt = VT_I2; vtIndex.iVal = 0;
                            
                strFolderID = (_bstr_t)pFields->GetItem(vtIndex)->Value;
            }
            spRS->Close();          // TODO: Figure out if this can be reused...

            if (strFolderID.length() != 0)
            {
                // We could resolve the folder... Now try to find the resource

                Query = "SELECT resourcename FROM resources WHERE folderid = '";
                Query += strFolderID;
                Query += "' AND displayname = '";
                Query += (const char *)strResource;
                Query += "';";

                _RecordsetPtr spRS2;
                spRS2 = pConnection->Execute(Query, &rsAffected, adCmdText);

                if (VARIANT_FALSE == spRS2->EndOfFile)
                {
                    FieldsPtr pFields = NULL;
                    pFields = spRS2->GetFields();
                    _variant_t vtIndex; vtIndex.vt = VT_I2; vtIndex.iVal = 0;
                                
                    strTargetResource = (_bstr_t)pFields->GetItem(vtIndex)->Value;
                }

                spRS2->Close();
            }
        }
        catch (_com_error &e)
        {
            CDebug::Format(L"CExtension::TranslateURL: COM Error (%s)", (const TCHAR *)e.Description());
        }

        if (pConnection) if (pConnection->State == adStateOpen) pConnection->Close();

        if (strTargetResource.length() != 0)
        {
            // Build a new URL looking like: /nar.asp?rsc=[resourcename]
            strURL = "/nar.asp?rsc=";
            strURL += (const char *)strTargetResource;
        }
    }

    pReturn = new char[strURL.GetLength() + 1];

    if (pReturn)
    {
        pReturn[strURL.GetLength()] = 0;
        memcpy(pReturn, (const char *)strURL, strURL.GetLength());

        CDebug::Format("CExtension::TranslateURL: Returning '%s'", pReturn);
    }
    else
        CDebug::Format("CExtension::TranslateURL: No mapping was made.");

    return pReturn;
}
Pagina: 1