I am hoping someone can explain the do's and don't's of Mach4/Lua and  macro scripts and GUI's and how they interplay.  
As I understand it there are two instances of Mach4 Lua code running simultaneously.  One for the GUI(screen load script) and one for running macros/gcode/movement?
I was told to create a module for code that is to be used by both the screen and macro scripts.  I have some code that I put in the mach4hobby\modules directory and named it rtMyModulse.lua. It contains 3 functions at this point. 
My ScrrenLoadScript contains:  rt=require "rtMyModule" in the load modules section which successfully instantiates rt for use in the screen.
The first two functions work as expected from both the a screen button and a call to a macro (m9002.mcs example below).
The third function rtProbeX(dir) also works in a button script: rt.rtProbeX(1).
However, when I call m9000 from the mdi, or from a button using: mc.mcCntlMdiExecute(inst,"m9000"), it calls rtProbeX and executes the first part past the 'quick strike' and then fails.
Can a macro run several mcCntlExecuteGcodeWait?
Can a function in a module be called by a macro and execute several mcCntlExecuteGcodeWait?
Can you mcCntlSetLastError from a macro?
Can a function in a module be called by a macro and execute mcCntlSetLastError?
I've read that Lua does not have real threads but do the Gui and macro scripts not communicate/syncronize through callbacks or coroutine?
Are there any whitepapers on Mach4 structure and interplay?
rtMyModule.lua
ocal rtModule = {}
  local inst = mc.mcGetInstance()
  local profile = mc.mcProfileGetName(inst)
  local path = mc.mcCntlGetMachDir(inst)
  
  function rtModule.rtMessage(msg)
    wx.wxMessageBox(msg)
  end
  
  function rtModule.rtAudio(fileName)
    local audio=wx.wxSound(path.."\\Sounds\\"..fileName..".wav",inst)
    audio:Play()
  end
  function rtModule.rtAudioCountDown(StartNum,EndNum)
    local i=StartNum
    while i>=EndNum do
      rtModule.rtAudio(""..i)
      wx.wxMilliSleep(900)
      i=i-1
    end  
  end
  
 function rtModule.rtProbeX(Dir)
  local r1,r2,r3,retVal,rc
  --  local inst=mc.mcGetInstance()
  local xStart,rc
  xStart=mc.mcAxisGetPos(inst,0)-- Save starting X pos
  -- mc.mcCntlSetLastError(inst,"")
  mc.mcCntlGcodeExecuteWait(inst,"G31 X0 F4")  -- Quick strike
  r1,rc=mc.mcAxisGetProbePos(inst,0,false)
  mc.mcCntlGcodeExecuteWait(inst,'G01 X'..tostring(mc.mcAxisGetPos(inst,0)+0.030*Dir)..' F4') --Back off 
  mc.mcCntlGcodeExecuteWait(inst,'G31 X0 F0.5')  -- First slow strike
  r1,rc=mc.mcAxisGetProbePos(inst,0,false)
  mc.mcCntlGcodeExecuteWait(inst,'G01 X'..tostring(mc.mcAxisGetPos(inst,0)+0.030*Dir)..' F4') --Back off 
  mc.mcCntlGcodeExecuteWait(inst,'G31 X0 F0.5') -- Second slow strike
  r2,rc=mc.mcAxisGetProbePos(inst,0,false)
  mc.mcCntlGcodeExecuteWait(inst,'G01 X'..tostring(mc.mcAxisGetPos(inst,0)+0.030*Dir)..' F4')  --Back off 
  mc.mcCntlGcodeExecuteWait(inst,'G31 X0 F0.5') -- Third slow strike
  r3,rc=mc.mcAxisGetProbePos(inst,0,false)
  mc.mcCntlGcodeExecuteWait(inst,'G01 F8 X'..xStart)--return to starting position
  retVal=(r1+r2+r3)/3  -- average the strikes
  --  mc.mcCntlSetLastError(inst,string.format("%1.4f - %1.4f - %1.4f ",r1,r2,r3))
  return retVal
end
return rtModule
m9000.mcs
--m9000 lathe centering probe 
function m9000(hVars)
    local xDis=1
    local zDis=.25
    local zStart
    local zEnd
    local xPos
    local xNeg
    local flag, rc
    local rt = require "rtMyModule"
    local inst = mc.mcGetInstance() -- Get the current instance
    local nilPoundVar = mc.mcCntlGetPoundVar(inst,0)
    local message = ""
    if hVars ~= nil then
      flag, rc = mc.mcCntlGetLocalVarFlag(inst, hVars, mc.SV_X)
      if (flag == 1) then 
        xDis, rc = mc.mcCntlGetLocalVar(inst, hVars, mc.SV_X)
        if xDis==nil then
          xDis=1
        end
      end
      flag, rc = mc.mcCntlGetLocalVarFlag(inst, hVars, mc.SV_Z)
      if (flag == 1) then 
        zDis, rc = mc.mcCntlGetLocalVar(inst, hVars, mc.SV_Z)
        if zdis==nil then
          zDis=0.25
        end
      end
    end
    mc.mcAxisSetPos(inst,0,0)
    zStart,rc=mc.mcAxisGetPos(inst,2)
    zEnd=zStart-zDis
    mc.mcCntlGcodeExecuteWait(inst,'G0 F1 X'..xDis..'\nG0 F1 Z'..zEnd)
    --mc.mcCntlSetLastError(inst, "Probing for Positive X" )
    xPos= rt.rtProbeX(1)
    mc.mcCntlGcodeExecuteWait(inst,'G0 Z'..zStart)
    mc.mcCntlGcodeExecuteWait(inst,'G0 X'..-xDis)
    mc.mcCntlGcodeExecuteWait(inst,'G0 Z'..tostring(zStart-zDis))
    --mc.mcCntlSetLastError(inst, "Probing for Negative X" )
    xNeg= rt.rtProbeX(-1)
    mc.mcCntlGcodeExecuteWait(inst,'G0 Z'..zStart)
    mc.mcCntlGcodeExecuteWait(inst,'g01 f8 X'..tostring(2*xPos-(xPos-xNeg)))
    mc.mcAxisSetPos(inst,0,0)  
end	
if (mc.mcInEditor() == 1) then
    m9000(0) 
end
m9002.mcs
function m9002()  --testing load rtMyModule
 local inst = mc.mcGetInstance()
 
 mc.mcCntlGcodeExecuteWait(inst,"g1F4 x1")
 
 rt = require "rtMyModule"
 
 if rt==nil then
    wx.wxMessageBox("rt==nil")
  else
    rt.rtMessage('Another Hello')
  end
end
if mc.mcInEditor()==1 then
  m9002()
end
Can anyone enlighten this old dog as to why this fails and what the rules and regulations are for scripting screen use and macro use?
RT