You are correct, it moved the problem.
I’ll study the code looking for loops, but...
one thing to note, there are two uses of the data for IO, and both would force evaluation of length/encode. One puts data in the GUI, one sends data by Ethernet. When only the GUI code is forcing IO, there is no hang. It is the Ethernet IO that causes the hang.
Because the GUI forcing does not hang, it leads me to believe there are no loops in the code.
Below is some description of overall application. -> means order of operation. T == Thread#. I note where the hang is, and what statement removal fixes it.
Main
T1 -> put TVar -> Start T2 -> Start T3
Async Module (TChan1/2/3 input/output wrapper around Eth based server in another process)
(This module takes a function that sends and recv data so that it is independent from communication mechanism)
(There are 2 output channels, one for response to commands in TCHan1, and one for a stream of telemetry)
T2 -> take TChan1 (config) ->
Serialize -> (Hangs here)
Send Eth
T2 -> Read Eth ->
Deserialize ->
put TChan2 (data1)
put TChan3 (data2)
fetchTelemetryServer (Consumes from Async Module T2 and puts data in sequence for callback)
T3 -> tryTake MVar2 (server lock) ->
take TChan3 (data) ->
put TSequence (data) ->
put MVar2 (server unlock)
showOptionDialogServer (Produces for Async Module T2)
(Changes the config in a dialog and send it to the server to modify telemetry definition)
wxH Menu Callback -> take MVar2 (server lock) ->
take MVar1 (gui lock) ->
take TVar (config) ->
convert config to strings
display in dialog
pull strings from dialog
build modified config
put TVar (config) ->
put TChan1 (config) -> (Remove and no hang)
put MVar1 (gui unlock) ->
put MVar2 (server lock)
performTelemetryServer
(Takes data from telemetry and prepares it for painting)
wxH Timer Callback -> take MVar1 (gui lock) ->
take TSequence (data) ->
modify data
put Var (data2) ->
repaint ->
put MVar1 (gui unlock)
onPaint
(Update the graphs in the GUI)
wx Paint Callback -> tryTake MVar1 (gui lock) ->
get Var (data2) ->
get TVar (config) ->
draw on gui ->
put MVar1 (gui unlock)