Announcement

Collapse
No announcement yet.

Crash my Include on MTXDM.DLL

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Crash my Include on MTXDM.DLL

    Hi,
    I'm getting an crash that I can't fix. The crash concerns MTXDM.DLL.

    I've got this since I used Includes and split my code into 2 dlls.
    The includes are used by DLL1 to use the functions from DLL2.

    Each DLL is using a Critical Section which is dimmed, initialized in the LibMain (process attach) and deleted (process detach).
    For the rest, it enters and leaves the CS when accessing my global arrays (used by both DLL, loaded only once).

    I've tested it and found - strangly - that the CS from DLL2 is initialised first while the one from DLL1 is initialised after that one. Apparently the include triggers the second DLL first.
    I got this problem with a VB app, calling (PB) DLL1. So I wrote a little PB exe that does nothing more than call the DLL1 (see code below). All goes well, the code is running, entering and leaving the CS's and finishes. It provides the result and should finish. I declared DLL1 (no dynamic loading) so I don't do any freelibrary.
    When it should finish, it provides this error. I put messageboxes in the LibMain Process Attach and Detach, so I was expecting the Process Detach message boxes (where the CS is deleted). Didn't get them... Just the error.

    I do use some dynamic loading of different DLL, but I checked if they where unloaded: all ok. What am I doing wrong here?
    I found in the MSDN that this dll is for database connection and that this problem occurs when connecting and disconnecting to a database a lot. I use two connections to a database by means of SQL Tools but I only open them once. I even uninstalled MS PWS that was still on my system and reinstalled MDAC_TYPE.

    I don't really see how this is affected by the use of critical sections or includes. I've checked everything I know.

    Hope someone can help.

    Jeroen


    The code of the exe:
    Code:
    DECLARE FUNCTION TestFunction LIB "MyDLL.dll" ALIAS "TESTFUNCTION" (BYREF ComSession AS ComInfo) AS LONG
    ' COMINFO = one of my UDT
    
    FUNCTION PBMAIN() AS LONG
    
        LOCAL Com AS COMInfo
        Com.UserInput = "testinput to trigger: 15ma99"
        Com.Root = "C:\PBDLL\Test1"
    
        result& = Component_RO(Com)
        MSGBOX "result = " + TRIM$(Com.OutputString)
        ' this is still displayed
    
    END FUNCTION
     
    LibMain of DLL1 (same for DLl2 but with GSC2)
    
    FUNCTION LIBMAIN(BYVAL hInstance   AS LONG, _
                     BYVAL fwdReason   AS LONG, _
                     BYVAL lpvReserved AS LONG) EXPORT AS LONG
    
        ON ERROR RESUME NEXT
    
      SELECT CASE fwdReason
    
        CASE %DLL_PROCESS_ATTACH
            DIM GSC2 AS GLOBAL Critical_Section 
            InitializeCriticalSection GSC2
            MSGBOX "GSC2 INI"
           LIBMAIN = 1   'success!
          EXIT FUNCTION
    
        CASE %DLL_PROCESS_DETACH
            DeleteCriticalSection GSC2
            MSGBOX "GSC2 Deleted"
           LIBMAIN = 1   'success!
          EXIT FUNCTION          
     END SELECT
    END FUNCTION


    ------------------

  • #2
    Jeroen,

    Just don't delete the CS from the DLL. It will get deleted by ending the program that calls it anyway.

    I had the same problem, apparently we're not allowed to call DeleteCriticalSection from the DLL.


    Peter


    ------------------
    [email protected]
    [email protected]

    Comment


    • #3
      I'm afraid I absolutely cannot agree with that statement, Peter, since I've built a number of DLL's that use a critical section exactly like this.

      There is one important thing to check that can cause GPF's when dealing with CS's... if your copy of WIN32API.INC defines the CS structure with a length of less than 24 bytes then you need to update your WIN32API.INC files.

      WIN32API.INC http://www.powerbasic.com/files/pub/pbwin/win32api.zip


      ------------------
      Lance
      PowerBASIC Support
      mailto:[email protected][email protected]</A>
      Lance
      mailto:[email protected]

      Comment


      • #4
        Hi,

        Here's the 'progress': the deletecriticalsection is not the problem. The includes of the UDT and the functions is - contrary to what I though - is not the problem. I tried all options and the result is the same.
        I check my win32api and it's set to 24, so that should be alright. But it's not really a GPF.

        The problem is that with a certain entry, one of my functions where I use a CS, provides and error with is handled by an errorhandler. In this errorhandler I use LeaveCriticalSection, just to be on the safe sight. What probably happens is that this error is activated from a part where it has not entered the CS (yet).
        So the leave co-incides with another thread that - probably - just DID enter the CS. Then the global data are not safe anymore, proably causing the error. Also, the next entry hangs! I guess I has the same reason: it hangs on the line where it has to enter the CS. Apparently, the last thing it registered was the enter (and not the leave from the error handler). So it waits, and waits...

        Anyway, have to do some more testing and re-writing.

        Just one question (just for the record):
        It is allowed to have a LeaveCriticalSection in an error handler?

        Problem is : it still doesn't help my original problem: the crash on the mtxdm.dll. I found that - from my VB application - I don't even have to enter data and call the dll, to have a hang. I (have to) declare my dll, and that seems to be enough to have it hanging.
        I've done some research and found on MSDN and IBM that it has to do with ODBC, to be more precise, with connection pooling, related to MTX and the like.
        If I rename the mtxdm.dll, I get an error opening the SQL Server database from VB : undefined error (nice no?), but it opens all right and does do a select. Yet, when I call my PBDLL, it provides and error on the opening of the database. The hanging (on the close of the VB application) or error (on the close of the PB applications - see above), is gone!

        This is what I get:
        I always initialize SQLTools, check whether the database number is open, and if so, check if is the right database. If not, open the database I want. Normally, SQL Tools 'understands' that the database is already opened (by the VB app), so I don't have to open it anymore, just the initialise part is necessary.

        Code:
            result& = SQL_Initialize(3, 256, 240, 256, 3, 1, 0, 0)
            IF PrintInfo >= 5 THEN
                PRINT #FreeFile1&, "Set SQL_Initialize result = " + STR$(result&)
                PRINT #FreeFile1&, "Error = " + SQL_ErrorQuickAll
            END IF
        
            result& = SQL_THREAD(%THREAD_MAX, 812)  ' 256 statements , x 3 SQL Threads
            IF PrintInfo >= 5 THEN
                PRINT #FreeFile1&, "Set SQL_Thread result = " + STR$(result&)
                PRINT #FreeFile1&, "Error = " + SQL_ErrorQuickAll
            END IF
        
            result& = SQL_SetOptionStr(%OPT_TEXT_MAXLENGTH, "2000")
            result& = SQL_SetOptionStr(%SQL_WVARCHAR, "2000")
            result& = SQL_SetOptionStr(%OPT_DATALEN_UNKNOWN, "2000")
            IF PrintInfo >= 5 THEN
                PRINT #FreeFile1&, "Set Option result = " + STR$(result&)
                PRINT #FreeFile1&, "Error = " + SQL_ErrorQuickAll
            END IF
        
            result& = SQL_DataBaseIsOpen(DBNr)
            IF PrintInfo >= 5 THEN
                PRINT #FreeFile1&, "DBisopen result = " + STR$(result&)
                PRINT #FreeFile1&, "Error = " + SQL_ErrorQuickAll
            END IF
            
            IF result& <> -1 THEN
                
                result& = SQL_OpenDatabase(DBNR, "FILEDSN=" + Root + "\Includes\db1.dsn;UID=testlogin;PWD=123", %NOPROMPT)
                IF result& <> %SUCCESS AND result& <> %SUCCESS_WITH_INFO THEN
                    IF PrintInfo >= 5 THEN
                        PRINT #FreeFile1&, "Couldn't open DB."
                        PRINT #FreeFile1&, "Error = " + SQL_ErrorQuickAll
                    END IF
                    Woord$ = SQL_ErrorQuickAll
                    SQL_ErrorClearAll
                ELSE
                    Woord$ = ""
                END IF
            END IF
        
            IF LEFT$(LCASE$(SQL_DataBaseInfoStr(DBNR, %DB_USER_NAME)), 8) = "testloging" OR _
                LEFT$(LCASE$(SQL_DataBaseInfoStr(DBNR, %DB_USER_NAME)), 8) = "testlog" THEN
                'OK
                        
            ELSE
                IF PrintInfo >= 5 THEN
                    PRINT #FreeFile1&, "SQL_DataBaseInfoStr result = " + STR$(result&)
                    PRINT #FreeFile1&, "Error = " + SQL_ErrorQuickAll
                END IF
                
                result& = SQL_CLOSEDATABASE(DBNr)
                IF PrintInfo >= 5 THEN
                    PRINT #FreeFile1&, "SQL_CLOSEDATABASE result = " + STR$(result&)
                    PRINT #FreeFile1&, "Error = " + SQL_ErrorQuickAll
                END IF
        
                IF PrintInfo >= 5 THEN
                    PRINT #FreeFile1&,
                    PRINT #FreeFile1&, "Start Opening DB"
                END IF
                result& = SQL_OpenDatabase(DBNR, Root + "\Includes\db1.dsn;UID=testlogin;PWD=123",%NOPROMPT)
                IF result& <> %SUCCESS AND result& <> %SUCCESS_WITH_INFO THEN
                    IF PrintInfo >= 5 THEN
                        PRINT #FreeFile1&, "Couldn't open DB."
                        PRINT #FreeFile1&, "Error = " + SQL_ErrorQuickAll
                        PRINT #FreeFile1&, "Error = " + SQL_ErrorQuickOne
                    END IF
                    Woord$ = SQL_ErrorQuickAll
                    SQL_ErrorClearAll
                ELSE
                    Woord$ = ""
                END IF
            END IF
        Resulting in the following output:

        Set SQL_Initialize result = 999000048
        Error = [70213.500] SQL_Initialize -1 -1 -1 999000048 #0048 0 -- [Perfect Sync][SQL Tools] Can't Be Done
        Set SQL_Thread result = 0
        Error =
        Set Option result = 0
        Error = [70213.500] SQL_Initialize -1 -1 -1 999000048 #0048 0 -- [Perfect Sync][SQL Tools] Can't Be Done | [70213.500] SQL_Initialize -1 -1 -1 999000048 #0048 0 -- [Perfect Sync][SQL Tools] Can't Be Done | [70213.500] SQL_Initialize -1 -1 -1 999000048 #0048 0 -- [Perfect Sync][SQL Tools] Can't Be Done | [70213.500] SQL_Initialize -1 -1 -1 999000048 #0048 0 -- [Perfect Sync][SQL Tools] Can't Be Done | [70213.500] SQL_Initialize -1 -1 -1 999000048 #0048 0 -- [Perfect Sync][SQL Tools] Can't Be Done
        DBisopen result = 0
        Error =
        Couldn't open DB.
        Error = [70213.500] SQL_Initialize -1 -1 -1 999000048 #0048 0 -- [Perfect Sync][SQL Tools] Can't Be Done | [70213.500] SQL_Initialize -1 -1 -1 999000048 #0048 0 -- [Perfect Sync][SQL Tools] Can't Be Done
        SQL_DataBaseInfoStr result = -2
        Error = [70213.500] SQL_DatabaseInfoStr 1 -1 -1 999000031 #0031 0 -- [Perfect Sync][SQL Tools] DB Not Open | [70213.500] SQL_DatabaseInfoStr 1 -1 -1 999000031 #0031 0 -- [Perfect Sync][SQL Tools] DB Not Open
        SQL_CLOSEDATABASE result = 999000031
        Error = [70213.500] SQL_CloseDatabase 1 -1 -1 999000031 #0031 0 -- [Perfect Sync][SQL Tools] DB Not Open

        Start Opening DB
        Couldn't open DB.
        Error = [70213.500] SQL_Initialize -1 -1 -1 999000048 #0048 0 -- [Perfect Sync][SQL Tools] Can't Be Done | [70213.500] SQL_Initialize -1 -1 -1 999000048 #0048 0 -- [Perfect Sync][SQL Tools] Can't Be Done


        Let make this sure: I'm sure SQLTools has not been started/initialized before! I even rebooted and tried it again. My VB app doesn't call SQL Tools before in any way, other than the indirect link via the declare of my dll where it is used.
        So I tested if SQL Tools still worked ok:
        Code:
        $INCLUDE "C:\PBDLL\SQLTools\SQL_PRO2.INC"
        
        ' renamed mtxdm.dll (system) to mtxdm2.dll
        
        FUNCTION PBMAIN() AS LONG
        
            result& = SQL_INIT
            IF result& <> 0 THEN
                MSGBOX "SQL_INIT result = " + STR$(result&) + ";" + SQL_ERRORQUICKALL
                EXIT FUNCTION
            END IF
        
            result& = SQL_OPENDB("FILEDSN=C:\PBDLL\Includes\db1.dsn")
            IF result& <> 0 THEN
                MSGBOX "SQL_OPENDB result = " + STR$(result&) + ";" + SQL_ERRORQUICKALL
            END IF
        
            result& = SQL_Stmt(%IMMEDIATE, "Select ID from Table1 Where ID < 50")
            IF result& <> %SUCCESS AND result& <> %SUCCESS_WITH_INFO THEN
                MSGBOX "SQL_stmt result = " + STR$(result&) + ";" + SQL_ERRORQUICKALL
                result& = SQL_SHUTDOWN
                IF result& <> 0 THEN
                    MSGBOX "SQL_SHUTDOWN result = " + STR$(result&) + ";" + SQL_ERRORQUICKALL
                    EXIT FUNCTION
                END IF
                EXIT FUNCTION
            ELSEIF result& = %SQL_NO_DATA THEN
                MSGBOX "SQL_stmt NODATA : result = " + STR$(result&) + ";" + SQL_ERRORQUICKALL
                result& = SQL_SHUTDOWN
                IF result& <> 0 THEN
                    MSGBOX "SQL_SHUTDOWN result = " + STR$(result&) + ";" + SQL_ERRORQUICKALL
                    EXIT FUNCTION
                END IF
                EXIT FUNCTION
            END IF
        
            result& = SQL_SHUTDOWN
            IF result& <> 0 THEN
                MSGBOX "SQL_SHUTDOWN result = " + STR$(result&) + ";" + SQL_ERRORQUICKALL
                EXIT FUNCTION
            END IF
        
            MSGBOX "DONE"
        END FUNCTION
        So it asks for the login name and mentiones the 'changes of context to database 'testdb' and that's it: done! All goes well.

        So it's not SQL tools, it's the combination of SQL Tools with VB.
        Anybody had similar problems before? I'm gonna test on different systems, so...


        Regards
        Jeroen Brouwers

        ------------------


        [This message has been edited by jeroen brouwers (edited March 18, 2001).]

        Comment


        • #5
          Hi, just an update:
          I've reinstalled the odbc files from windows (win98_37.cab) and reinstalled SQL Tools and reinstalled MDAC_Type (2.5). The result is that PB runs ok, but if I call the DLL from my VB app, it still provides the same error.
          So I reinstalled VB, just put SP5 over it to be on the safe side: no luck.

          Hope you can help
          Jeroen

          ------------------

          Comment


          • #6
            Jeroen --

            Your program is starting out with a very clear indication that something is wrong.

            > Set SQL_Initialize result = 999000048
            > Error = [70213.500] SQL_Initialize -1 -1 -1 999000048 #0048 0 --
            > [Perfect Sync][SQL Tools] Can't Be Done

            As described in the SQL Tools documentation, the SQL_Initialize function returns "Can't Be Done" (error 999000048) when you try to initialize the DLL a second time. I just reviewed the source code for SQL Tools to make sure, and I promise you that if you are seeing that error, you are calling SQL_Initialize more than once. Nothing else can cause that error.

            "Initialize" means exactly that. You must initialize SQL Tools before you use it, and after you have done it once you don't need to -- and should not -- do it again. The error trail that you posted appears to show SQL_Initialize being called over and over again, many times. And if that is happening it seems to me that threads must be involved, right?

            IMO there must be something going seriously wrong with your threading. Unless VB is creating threads, which I don't believe it can do, then this not a VB problem. You have confirmed that it is not a SQL Tools problem, so I'd look hard at your source code.

            Based on what you posted, I can't speculate about the source of the problem. It is very jumbled, as if many threads were all executing at once.

            I would suggest using the SQL Tools "Trace" functions to run your program in the Trace Mode. I suspect that you will see many errors taking place, all with different thread numbers. (The thread number is always included in the trace file.)

            The trace file will show you exactly what functions are being called, the parameters that are being passed to them, their return values, and any error messages that are being generated. If you look closely at the Trace File you should be able to figure out what is going wrong.

            -- Eric


            ------------------
            Perfect Sync Development Tools
            Perfect Sync Web Site
            Contact Us: mailto:[email protected][email protected]</A>

            [This message has been edited by Eric Pearson (edited March 18, 2001).]
            "Not my circus, not my monkeys."

            Comment


            • #7
              Are your DLLs loaded dynamically? This is not an issue I know in detail, but it
              seems possible that DLL1 could be causing DLL2 to execute before you think if
              Windows is causing DLL1 to load DLL2 automatically. It might be worth a small
              experiment with using LoadLibrary instead of implicit function Declares.

              ------------------
              Tom Hanlin
              PowerBASIC Staff

              Comment


              • #8
                Eric,
                I totally agree that there's something wrong. I used the trace to see what exactly but couldn't find much.
                Apparently, something is already calling SQL_INIT before. I'll have to test some more what it might be.
                I'll look into my threading to see what might be going wrong.

                I wrote a little dll that dynamically loads the dll. My VB app now calls this dll so the real one is dynamically loaded and unloaded (which can't be done in VB).
                The problem now is - both in VB and in a PB test exe - that the Freelibrary won't work. It completely hangs on that statement!

                Any ideas what I (still) might be doing wrong??

                Greetings
                Jeroen


                ------------------

                Comment


                • #9
                  Hi, just an update:

                  I ran into SQL_SHUTDOWN used in the LibMain caused the hanging.
                  RTFM I guess.....




                  ------------------

                  Comment


                  • #10
                    Right, that's covered in the Help File under "Special Considerations for DLL Programmers". I'll make sure we add some more links to the next version of the Help File, to link the SQL_Shutdown page to that page.

                    -- Eric


                    ------------------
                    Perfect Sync Development Tools
                    Perfect Sync Web Site
                    Contact Us: mailto:[email protected][email protected]</A>

                    [This message has been edited by Eric Pearson (edited March 20, 2001).]
                    "Not my circus, not my monkeys."

                    Comment

                    Working...
                    X