[Done] Crash with SendNetworkData

Post bugreports for the Mac OSX version here
User avatar
mk-soft
Always Here
Always Here
Posts: 5337
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

[Done] Crash with SendNetworkData

Post by mk-soft »

The network functions are as described ThreadSafe.

If you outsource the sending of data to another thread and the connection to the partner fails, SendNetworkData crashed.
With Windows and Linux, SendNetworkData returns a result of less than zero and can be aborted.

Server

Code: Select all

;-TOP

CompilerIf #PB_Compiler_Thread = 0
  CompilerError "Use Compiler Option ThreadSafe!"
CompilerEndIf

InitNetwork()

Enumeration Windows
  #Main
EndEnumeration

Global ExitApplication
Global MutexServer = CreateMutex()

Procedure thServer(id)
  Protected ServerID, Event, ConnectionID, cnt
  Protected *buffer = AllocateMemory($FFFF)
  
  ServerID = CreateNetworkServer(#PB_Any, 6037)
  If ServerID = 0
    Debug "Error: Create NetworkServer!"
    ProcedureReturn 0
  Else
    Debug "Create NetworkServer"
  EndIf
  
  Repeat
    LockMutex(MutexServer)
    Event = NetworkServerEvent(ServerID)
    ConnectionID = EventClient()
    UnlockMutex(MutexServer)
    Select Event
      Case #PB_NetworkEvent_Connect
        Debug "Client Conneceted ID " + ConnectionID
      Case #PB_NetworkEvent_Data
        cnt = ReceiveNetworkData(ConnectionID, *buffer, $FFFF)
        Debug "Receive Data ID " + ConnectionID + " / Len " + cnt
      Case #PB_NetworkEvent_Disconnect
        Debug "Client Disconneceted ID " + ConnectionID
      Default
        Delay(10)
    EndSelect
    
  Until ExitApplication 
  
  Debug "Close NetworkServer"
  CloseNetworkServer(ServerID)
  Debug "Exit Thread"
  
EndProcedure

Procedure Main()
  Protected thServer
  
  If OpenWindow(#Main, 80, 80, 200, 60, "Server" , #PB_Window_SystemMenu)
    
    thServer = CreateThread(@thServer(), 0)
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          ExitApplication = #True
          If WaitThread(thServer, 1000) = 0
            KillThread(thServer)
          EndIf
          Break
      EndSelect
    ForEver
    
  EndIf
  
EndProcedure : Main()
[/size]

Client

Code: Select all

;-TOP

CompilerIf #PB_Compiler_Thread = 0
  CompilerError "Use Compiler Option ThreadSafe!"
CompilerEndIf

InitNetwork()

Enumeration Windows
  #Main
EndEnumeration

Enumeration Gadgets
  
EndEnumeration

Enumeration Status
  #MainStatusBar
EndEnumeration

Global ExitApplication, ExitSendData
Global ConnectionID

Procedure thClient(id)
  Protected Event, cnt
  Protected *buffer = AllocateMemory($FFFF)
  
  ConnectionID = OpenNetworkConnection("127.0.0.1", 6037)
  If ConnectionID = 0
    Debug "Error: Create NetworkClient!"
    ProcedureReturn 0
  Else
    Debug "Create NetworkClient"
  EndIf
  
  Repeat
    Event = NetworkClientEvent(ConnectionID)
    Select Event
      Case #PB_NetworkEvent_Data
        cnt = ReceiveNetworkData(ConnectionID, *buffer, $FFFF)
        Debug "Receive Data ID " + ConnectionID + " / Len " + cnt
      Case #PB_NetworkEvent_Disconnect
        Debug "Server Disconneceted"
        ExitSendData = #True
        Break
      Default
        Delay(100)
    EndSelect
    
  Until ExitApplication 
  
  Debug "Close NetworkClient"
  CloseNetworkConnection(ConnectionID)
  ConnectionID = 0
  Debug "Exit Thread Client"
  
EndProcedure

Procedure thSendData(ConnectionID)
  Protected cnt
  Repeat
    cnt = SendNetworkData(ConnectionID, @"Hello World!", 12)
    Debug "Send " + cnt
    If cnt < 0
      Debug "Send Error"
      Break
    EndIf
    Delay(40)
  Until ExitApplication ; Or ExitSendData
  
  Debug "Exit Thread SendData"
  
EndProcedure

Procedure Main()
  Protected thClient, thSend
  
  If OpenWindow(#Main, 80, 180, 200, 60, "Client" , #PB_Window_SystemMenu)
    ButtonGadget(0, 10, 10, 180, 30, "Start Send")
    
    thClient = CreateThread(@thClient(), 0)
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          ExitApplication = #True
          If thClient
            If WaitThread(thClient, 1000) = 0
              KillThread(thClient)
            EndIf
          EndIf
          If thSend
            If WaitThread(thSend, 1000) = 0
              KillThread(thSend)
            EndIf
          EndIf
          Break
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 0
              If ConnectionID And Not IsThread(thSend)
                thSend = CreateThread(@thSendData(), ConnectionID)
              EndIf
          EndSelect
      EndSelect
    ForEver
    
  EndIf
  
EndProcedure : Main()
[/size]

Current solution:
Check the client port before sending the data.

Code: Select all

; ***************************************************************************************
; Bugfix MacOS SendNetworkData over Threads. mk-soft, 27.10.2019, Version 1.01
; Update 07.05.2020 Version 1.02

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  
  Import ""
    CFSocketIsValid(Socket) ; -> Boolean
  EndImport
  
  Procedure FixSendNetworkData(ClientID, MemoryBufer, Length)
    If CFSocketIsValid(ClientID)
      ProcedureReturn SendNetworkData(ClientID, MemoryBufer, Length)
    Else
      ProcedureReturn -2
    EndIf
  EndProcedure
  
  Macro SendNetworkData(ClientID, MemoryBufer, Length)
    FixSendNetworkData(ClientID, MemoryBufer, Length)
  EndMacro
  
CompilerEndIf

; ***************************************************************************************
[/size]
Last edited by mk-soft on Thu May 07, 2020 4:38 pm, edited 1 time in total.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: Crash with SendNetworkData

Post by Josh »

Wiso sind deine Codes immer so klein geschrieben? Bei mir hier ist das nicht lesbar.
sorry for my bad english
User avatar
mk-soft
Always Here
Always Here
Posts: 5337
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Crash with SendNetworkData

Post by mk-soft »

In diesen fall nur, damit man nicht so viel scrollen muss...

In this case only so that you don't have to scroll so much...
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 5337
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Crash with SendNetworkData

Post by mk-soft »

My help solution work not every time :(
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 5337
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Crash with SendNetworkData

Post by mk-soft »

There seems to be a problem with the socket event loop and the 'SendNetworkData' if they run in different threads.
The thread with the Network Event Loop (Function 'NetworkClientEvent') must be called at least twice as often as the thread with the data send. It also helps to check the connection before sending (CFSocketIsValid).

Runs more stable ...

Code: Select all

; ***************************************************************************************
; Bugfix MacOS SendNetworkData over Threads. mk-soft, 27.10.2019, Version 1.01
; Update 07.05.2020 Version 1.02

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  
  Import ""
    CFSocketIsValid(Socket) ; -> Boolean
  EndImport
  
  Procedure FixSendNetworkData(ClientID, MemoryBufer, Length)
    If CFSocketIsValid(ClientID)
      ProcedureReturn SendNetworkData(ClientID, MemoryBufer, Length)
    Else
      ProcedureReturn -2
    EndIf
  EndProcedure
  
  Macro SendNetworkData(ClientID, MemoryBufer, Length)
    FixSendNetworkData(ClientID, MemoryBufer, Length)
  EndMacro
  
  Procedure FixSendNetworkString(ClientID, String.s, Format = #PB_UTF8)
    If CFSocketIsValid(ClientID)
      ProcedureReturn SendNetworkString(ClientID, String, Format)
    Else
      ProcedureReturn -2
    EndIf
  EndProcedure
  
  Macro SendNetworkString(ClientID, String, Format = #PB_UTF8)
    FixSendNetworkString(ClientID, String, Format)
  EndMacro
  
CompilerEndIf

; ***************************************************************************************
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Fred
Administrator
Administrator
Posts: 16623
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Crash with SendNetworkData

Post by Fred »

This report isn't clear to me, do you try to still use SendNetworkData() after a disconnect event ? If yes
it's not supported and can lead to crash
User avatar
mk-soft
Always Here
Always Here
Posts: 5337
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Crash with SendNetworkData

Post by mk-soft »

Fred wrote: Sun Feb 18, 2024 9:43 am This report isn't clear to me, do you try to still use SendNetworkData() after a disconnect event ? If yes
it's not supported and can lead to crash
Hello Fred,
It's exactly as you wrote it. The thread continues to try to send, even though the partner has ended the connection or was interrupted by an error.

With Linux and Window, SendNetworkData returns an error (-1). On macOS it crashes because macOS probably destroys the resource for the connection immediately.

The solution I am currently using is to check the connection for errors before sending.

Code: Select all

Procedure _SendNetworkData(ClientID, *MemoryBuffer, Length)
    Protected r1
    Protected error_code
    Protected error_code_size = SizeOf(error_code)
    
    r1 = getsockopt_(ConnectionID(ClientID), #SOL_SOCKET, #SO_ERROR, @error_code, @error_code_size)
    If r1 <= 0
      r1 = error_code
    EndIf
    
    If r1
      ProcedureReturn -1
    Else
      ProcedureReturn SendNetworkData(ClientID, *MemoryBuffer, Length)
    EndIf
  EndProcedure
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Fred
Administrator
Administrator
Posts: 16623
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Crash with SendNetworkData

Post by Fred »

You are right, something was different on OS X (!). I added the SO_NOSIGPIPE option to the socket: https://forums.developer.apple.com/forums/thread/107307

As I can't reproduce it, may be you can try it with the next beta !
User avatar
mk-soft
Always Here
Always Here
Posts: 5337
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Crash with SendNetworkData

Post by mk-soft »

Ok, Thanks ;)
I will perform a stress test with the next beta.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Fred
Administrator
Administrator
Posts: 16623
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Crash with SendNetworkData

Post by Fred »

Could you try it ? :)
User avatar
mk-soft
Always Here
Always Here
Posts: 5337
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Crash with SendNetworkData

Post by mk-soft »

Sorry, I had forgotten.

A quick test with my TCP module adapted that is sent further in the thread when the connection is closed.
SendNetworkData now comes back with an error ;)

Looks good so far.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Fred
Administrator
Administrator
Posts: 16623
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: [Done] Crash with SendNetworkData

Post by Fred »

Thanks !
Post Reply