CreateThread(CRASH AND BURN)

Just starting out? Need help? Post your questions and find answers here.
nospam
Enthusiast
Enthusiast
Posts: 130
Joined: Mon Nov 12, 2012 9:15 am

CreateThread(CRASH AND BURN)

Post by nospam »

I'm trying to get a small client/server running on Linux x64, unicode, though the OS shouldn't matter as this is stock, out of the box PB code. The code runs fine and does exactly what it should as it's written below (client connects, server says '200 Hello' and client responds with 'EXEC SOME CMD'), except that the UI is locked, which is why I need this running on a thread. However if I uncomment marked line 1 and comment marked line 2 out, everything crashes and burns. Can anyone advise on what I'm doing wrong?
[WARNING] test.pb (Line: 57)
[WARNING] GdK (CRITICAL): IA__gdk_window_get_events: assertion 'GDK_IS_WINDOW (window)' failed
[WARNING] test.pb (Line: 57)
[WARNING] GLib-GObject (CRITICAL): g_object_unref: assertion 'G_IS_OBJECT (object)' failed

Code: Select all

EnableExplicit

Procedure BlockingProxy(*Port.i)
   
   InitNetwork()
   
   #BufferLen = 65535
   Define *Buffer = AllocateMemory(#BufferLen)
   Define thisEvent.i
   Define ClientID.i
   Define Quit.i
   
   If CreateNetworkServer(0, *Port)
      
      Repeat
         
         thisEvent = NetworkServerEvent()
         
         If thisEvent
            
            ClientID = EventClient()
            
            Select thisEvent
               Case #PB_NetworkEvent_Connect
                  SendNetworkString(ClientID, "200 Ready" + Chr(13) + Chr(10))
               Case #PB_NetworkEvent_Data
                  ReceiveNetworkData(ClientID, *Buffer, #BufferLen)
                  MessageRequester("", "Client sent: " + PeekS(*Buffer, -1, #PB_Ascii), 0)
               Case #PB_NetworkEvent_Disconnect
                  Quit = #True
                  
            EndSelect
         EndIf
         
      Until Quit = #True
      
      CloseNetworkServer(0)
      
   Else
      
      MessageRequester("Error", "Can't create server.", 0)
      
   EndIf
   
EndProcedure

Define MainQuit.i
Define MainEvent.i

OpenWindow(0, 250, 68, 504, 477, "Proxy Test",  #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)

; CreateThread(@BlockingProxy(), 1119)  ; <----- crash & burn ****** MARK 1
BlockingProxy(1119)  ; <----- works as designed ****** MARK 2;

Repeat
   
   MainEvent = WaitWindowEvent()
   
   Select MainEvent
      Case #PB_Event_CloseWindow
         MainQuit = 1
   EndSelect
   
Until MainQuit = 1
User avatar
idle
Always Here
Always Here
Posts: 5835
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: CreateThread(CRASH AND BURN)

Post by idle »

You can't use a MessageRequester in a thread on linux
you'll have to marshal it through a fifo

Code: Select all

EnableExplicit

Global gFifoMutex = CreateMutex()
Global NewList glMsg.s()

Procedure push(msg.s)
   LockMutex(gFifoMutex)
   If ListSize(glMsg())
    LastElement(gLmsg())
   EndIf  
   AddElement(glmsg())
   glmsg() = msg
   UnlockMutex(gFifoMutex)
EndProcedure 

Procedure.s pop() 
   Protected temp.s
   LockMutex(gFifoMutex)
   FirstElement(glmsg())
   temp = glmsg()
   DeleteElement(glmsg())
   UnlockMutex(gFifoMutex)
   ProcedureReturn temp 
 EndProcedure   

Procedure BlockingProxy(Port.i)
   
   InitNetwork()
   
   #BufferLen = 65535
   Define *Buffer = AllocateMemory(#BufferLen)
   Define thisEvent.i
   Define ClientID.i
   Define Quit.i
   
   If CreateNetworkServer(0, Port)
      
      push("Created server")
      
      Repeat
         
         thisEvent = NetworkServerEvent()
         
         If thisEvent
            
            ClientID = EventClient()
            
            Select thisEvent
               Case #PB_NetworkEvent_Connect
                  SendNetworkString(ClientID, "200 Ready" + Chr(13) + Chr(10))
                   push("Connect event")
               Case #PB_NetworkEvent_Data
                  ReceiveNetworkData(ClientID, *Buffer, #BufferLen)
                  push("Client sent: " + PeekS(*Buffer, -1, #PB_Ascii))
               Case #PB_NetworkEvent_Disconnect
                  Quit = #True
                  
            EndSelect
         EndIf
         
      Until Quit = #True
      
      CloseNetworkServer(0)
      
   Else
      
     push("Can't create server.")
      
   EndIf
   
EndProcedure

   


Define MainQuit.i
Define MainEvent.i

OpenWindow(0, 250, 68, 504, 477, "Proxy Test",  #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)

 CreateThread(@BlockingProxy(), 1119)  ; <----- crash & burn ****** MARK 1
;BlockingProxy(1119)  ; <----- works as designed ****** MARK 2;

Repeat
   
   MainEvent = WaitWindowEvent(30)
   
   Select MainEvent
      Case #PB_Event_CloseWindow
         MainQuit = 1
   EndSelect
   
   If ListSize(glMsg())
      MessageRequester("server",pop())
   EndIf    
   
Until MainQuit = 1
Windows 11, Manjaro, Raspberry Pi OS
Image
nospam
Enthusiast
Enthusiast
Posts: 130
Joined: Mon Nov 12, 2012 9:15 am

Re: CreateThread(CRASH AND BURN)

Post by nospam »

idle wrote:You can't use a MessageRequester in a thread on linux
Brilliant. Idle to the rescue again. Thanks for the code help, it works. I'll study it before I use it proper. I'll also crack a cold tinny for ya, mate. Of course, I'll have to drink it too :mrgreen:

Oh, and the Hungarian notation unmasks you as another old timer.

Cheers.
User avatar
idle
Always Here
Always Here
Posts: 5835
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: CreateThread(CRASH AND BURN)

Post by idle »

I could have done with that beer yesterday!

I just noticed Fred has implemented threadsafe GUI Set functions eg SetGadgetText
So you can set gadget states on the main thread from a client thread

Code: Select all

EnableExplicit

Procedure BlockingProxy(Port.i)
   
   InitNetwork()
   
   #BufferLen = 65535
   Define *Buffer = AllocateMemory(#BufferLen)
   Define thisEvent.i
   Define ClientID.i
   Define Quit.i
   
   If CreateNetworkServer(0, Port)
           
       SetGadgetText(1,"Created Server") 
      Repeat
         
         thisEvent = NetworkServerEvent()
         
         If thisEvent
            
            ClientID = EventClient()
            
            Select thisEvent
               Case #PB_NetworkEvent_Connect
                  SendNetworkString(ClientID, "200 Ready" + Chr(13) + Chr(10))
                  SetGadgetText(1,"Client Connected") 
               Case #PB_NetworkEvent_Data
                  ReceiveNetworkData(ClientID, *Buffer, #BufferLen)
                  SetGadgetText(1,"Client sent: " + PeekS(*Buffer, -1, #PB_Ascii))
               Case #PB_NetworkEvent_Disconnect
                  Quit = #True
                  
            EndSelect
         EndIf
         
      Until Quit = #True
      
      CloseNetworkServer(0)
      
   Else
      
    SetGadgetText(1,"Can't create server.")
      
   EndIf
   
EndProcedure

   


Define MainQuit.i
Define MainEvent.i
Define lastmsg.s 

OpenWindow(0, 250, 68, 504, 477, "Proxy Test",  #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
StringGadget(1,-130,5,120,30,"") 

CreateThread(@BlockingProxy(), 1119) 

Repeat
   
   MainEvent = WaitWindowEvent(5)
  
   Select MainEvent
      Case #PB_Event_CloseWindow
         MainQuit = 1
    
   EndSelect
   
   If  GetGadgetText(1) <> lastmsg  ;still need to test manually for a change 
      lastmsg = GetGadgetText(1) 
      MessageRequester("Msg",GetGadgetText(1))
   EndIf    
   
Until MainQuit = 1
Windows 11, Manjaro, Raspberry Pi OS
Image
nospam
Enthusiast
Enthusiast
Posts: 130
Joined: Mon Nov 12, 2012 9:15 am

Re: CreateThread(CRASH AND BURN)

Post by nospam »

idle wrote:I could have done with that beer yesterday!
It was icy cold, bubbly and exceedingly soothing. You would have loved it.
I just noticed Fred has implemented threadsafe GUI Set functions eg SetGadgetText
So you can set gadget states on the main thread from a client thread
That works perfectly, thank you. It'll be great for debugging. I'm translating a NNTP proxy server I wrote in Visual Studio a couple of years back. I already made the VS code open source under GPL3 and I'll do the same with the PB version when it's done. While it's specifically written for communicating with NNTP servers and news reader clients it can be modified for SMTP, POP etc. I'll credit you in the notes for your help.

Thanks again. Your help is appreciated.
Post Reply