Page 1 of 1

crash calling proc with xml from a librarythread

Posted: Fri Aug 29, 2008 7:36 pm
by Lukaso
hi guys,

i have a problem (probably a logical one) from calling some procedures from a dll that are stored in the mainexe (small plugininterface). i use more than 100 procedures without problems but this xml stuff is makes my crazy :cry:.

some code for testing purposes:

test.exe

Code: Select all

EnableExplicit

Structure uGWCoreOption
  sFile.s
  hXML.l
  hRootNode.l
  hMainNode.l
EndStructure

Define uGWCoreOption.uGWCoreOption

Procedure.b GWCoreOptionClose()
  Shared uGWCoreOption
  Protected bReturn.b = #False
  With uGWCoreOption
    If \hXML
      FreeXML(\hXML)
      \hXML = #Null
      \hRootNode = #Null
      \hMainNode = #Null
      bReturn = #True
    EndIf
  EndWith
  ProcedureReturn bReturn
EndProcedure

Procedure.b GWCoreOptionSave()
  Shared uGWCoreOption
  Protected bReturn.b = #False
  With uGWCoreOption
    If \hXML
      FormatXML(\hXML, #PB_XML_WindowsNewline | #PB_XML_ReduceNewline | #PB_XML_ReIndent)
      SaveXML(\hXML, \sFile, #PB_XML_StringFormat)
    EndIf
  EndWith
  ProcedureReturn bReturn
EndProcedure

Procedure.l GWCoreOptionInit()
  Shared uGWCoreOption
  With uGWCoreOption
    \sFile = "test.xml"
    \hXML = LoadXML(#PB_Any, \sFile, #PB_Unicode)
    If \hXML
      If XMLStatus(\hXML) = #PB_XML_Success
        \hRootNode = RootXMLNode(\hXML)
        \hMainNode = MainXMLNode(\hXML)
        If Not \hRootNode Or Not \hRootNode Or Not GetXMLNodeName(\hMainNode) = "gwcore"
          GWCoreOptionClose()
        EndIf
      Else
        GWCoreOptionClose()
      EndIf
    EndIf
    If Not \hXML
      DeleteFile(\sFile)
      \hXML = CreateXML(#PB_Any, #PB_Unicode)
      If \hXML
        \hRootNode = RootXMLNode(\hXML)
        \hMainNode = CreateXMLNode(\hRootNode)
        SetXMLNodeText(CreateXMLNode(\hRootNode, 0, #PB_XML_Comment), "gwcore preference file, manual editing can cause instability and crashes")
        SetXMLNodeName(\hMainNode, "gwcore")
        GWCoreOptionSave()
      EndIf
    EndIf
    ProcedureReturn \hXML
  EndWith
EndProcedure

Procedure.l GWCoreOptionGetModuleNode(sModule.s, bCreate.b = #False)
  Shared uGWCoreOption
  Protected lReturn.l = #Null, *lNode.l, lNode.l
  With uGWCoreOption
    If \hXML
      Repeat
        lNode + 1
        *lNode = XMLNodeFromPath(\hMainNode, "module[" + Str(lNode) + "]")
        If *lNode And GetXMLAttribute(*lNode, "name") = sModule
          lReturn = *lNode
          Break
        EndIf
      Until Not *lNode
      If Not lReturn And bCreate
        lReturn = CreateXMLNode(\hMainNode)
        SetXMLNodeName(lReturn, "module")
        SetXMLAttribute(lReturn, "name", sModule)
        GWCoreOptionSave()
      EndIf
    EndIf
  EndWith
  ProcedureReturn lReturn
EndProcedure

Procedure.b GWCoreOptionSetValueS(sModule.s, sName.s, sValue.s)
  Protected bReturn.b = #False, *lMainNode.l, *lNode.l
  *lMainNode = GWCoreOptionGetModuleNode(sModule)
  If *lMainNode
    *lNode = XMLNodeFromPath(*lMainNode, sName)
    If Not *lNode
      *lNode = CreateXMLNode(*lMainNode)
      SetXMLNodeName(*lNode, sName)
    EndIf
    If *lNode
      SetXMLNodeText(*lNode, sValue)
      GWCoreOptionSave()
      bReturn = #True
    EndIf
  EndIf
  ProcedureReturn bReturn
EndProcedure

GWCoreOptionInit()

OpenLibrary(0, "test.dll")
CallCFunction(0, "test", @GWCoreOptionSetValueS())

Delay(1000)

CloseLibrary(0)
test.dll

Code: Select all

Prototype.b GWCoreOptionSetValueS(sModule.s, sName.s, sValue.s)
Global GWCoreOptionSetValueS.GWCoreOptionSetValueS

EnableExplicit

Procedure Thread(lDummy.l)
  GWCoreOptionSetValueS("gwpp", "load", "true") ; <<< crash
EndProcedure

ProcedureDLL.l test(hProc.l)
  GWCoreOptionSetValueS = hProc
  
  ;CreateThread_(0, 0, @Thread(), 0, 0, 0)
  CreateThread(@Thread(), 0)

  ;GWCoreOptionSetValueS("gwpp", "load", "true") ; <<< works without problems

  Delay(100)
  ProcedureReturn #True
EndProcedure
Using GWCoreOptionSetValueS directly in the dll proc test() works but in a thread created in the dll i got a crash and i dont know why :(

i hate errors (mostly logical failure) that i can not explain myself.

thanks for helping :D

Posted: Fri Aug 29, 2008 9:05 pm
by srod
You haven't given us any code we can run! Missing the procedure : GWCoreOptionGetModuleNode() !

Posted: Fri Aug 29, 2008 9:23 pm
by Lukaso
sorry, deleted too much :lol:
edited ;)

Posted: Fri Aug 29, 2008 9:59 pm
by srod
Okay, this has nothing to do with the xml library. It is a string / threadsafety issue and I suspect a bug with PB. I am guessing that with the threadsafety switch, there may be some confusion between the two heaps used to store strings (one for the client, one for the dll) caused by thread local storage, although I will concede that Fred may simply say that we are doing something here which PB isn't designed to do. :wink:

Let me hack up a simple example which shows the problem and then we can think about a bug report.

Posted: Fri Aug 29, 2008 10:18 pm
by srod
Okay here is an example which shows the problem.

Set the threadsafety switch for both client and dll.


"test.dll" - compile to a dll.

Code: Select all

;Ensure threadsafe switch is enabled.

Prototype ClientFunction() 
  Global gClient.ClientFunction

Procedure Thread(lDummy.l) 
  gClient()
EndProcedure 

ProcedureDLL.l test(hProc.l) 
  gClient = hProc
  CreateThread(@Thread(), 0) 
  ProcedureReturn #True 
EndProcedure
"client.pb"

Code: Select all

;Ensure threadsafe switch is enabled.

Procedure ClientFunction() 
  a$=Str(10)  ;Crash here!
EndProcedure 

OpenLibrary(0, "test.dll") 
CallCFunction(0, "test", @ClientFunction()) 

Delay(1000) 

CloseLibrary(0)
The program is crashing at the first string manipulation (in this case the only such manipulation) within the client function called by the thread instigated in the dll.

The more I think about it the more I suspect that somehow the various string buffers are becoming 'entwined' because of various instance (module) variables. I'd certainly be interested in finding out! :)

The question now is whether we file a bug report?

Posted: Fri Aug 29, 2008 10:36 pm
by Lukaso
srod wrote:The question now is whether we file a bug report?
A fix in 4.30 would be nice ... big parts of my project using this :cry:
*need small workaround* :roll:

Image

Posted: Fri Aug 29, 2008 10:37 pm
by srod
Workaround : Shift all functions called within the thread into the dll or create the thread in the client program.

Shall I make the bug report or would you rather?

Posted: Fri Aug 29, 2008 10:40 pm
by Lukaso
srod wrote:Workaround : Shift all functions called within the thread into the dll or create the thread in the client program.

Shall I make the bug report or would you rather?
I think your english is better and you have more technical expirience :wink:

Posted: Fri Aug 29, 2008 10:41 pm
by srod
Okay. :)

Posted: Sat Aug 30, 2008 4:25 pm
by tinman
srod wrote:Okay here is an example which shows the problem.
Maybe I'm missing something but your client function take a parameter ("Procedure ClientFunction(a) "), but it's not being called with one ("gClient()").

Edit: I've read the bug report, so ignore what I said about stack corruption causing the crash. It's still there though :)

Posted: Sat Aug 30, 2008 4:35 pm
by srod
Yes, I altered the source so many times whilst testing that I obviously mixed up the dll and client from two different tests! :roll:

I have altered the post above now, but as you say; the problem remains! :)

Posted: Sat Aug 30, 2008 5:01 pm
by freak