This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
TheJebForge's profile picture

PCall Problem

Started by TheJebForge, 07 October 2014 - 04:21 PM
TheJebForge #1
Posted 07 October 2014 - 06:21 PM
Please help! I got stuck with error catching!
Code:

prToRun = "wtOS/apps/lol"
function runPr(prToRun)
	m.ccl(32768)
	m.tc(1)
	m.crp(1,1)
	os.pullEvent = oldpull
	function main()
	shell.run(prToRun)
	return
	end
  local ok, val = pcall(main)
  print(ok)
  print(val)
  os.pullEvent("key")
  --if ok then
  --main()
  --else
  --shell.run("wtOS/bsod "..'"'..val..'" '..prToRun)
  --end
  os.pullEvent = os.pullEventRaw
  m.ccl(dbg)
  redrawScr()
  return
end
LOL file contains:

losfmasd;fnsdlagsnfgklnadf;gdf;gkn
bsod file:

os.loadAPI("wtOS/apis/m")
Args = { ... }
m.ccl(2048)
m.tc(32768)
m.bc(1)
m.cpr("wtOS",2)
m.bc(2048)
m.tc(1)
m.tpr("A problem has been detected and wtOS has been terminated this program to prevent damage to your computer.",1,4)
write("\n\nThe problem seems to be caused by file: \n"..Args[2])
m.tc(16384)
m.cpr(Args[1],12)
m.tc(1)
m.cpr("Press Any Button to Continue",18)
os.pullEvent("key")
return
That all works fine, but when error found, it prints ok = true… true cant be!
Please fix my error catcher. :(/>
This code is for my OS!
Edited on 07 October 2014 - 04:21 PM
Lyqyd #2
Posted 07 October 2014 - 06:25 PM
Shell.run uses os.run, which in turn uses pcall. That pcall catches the error safely, prints it, then causes the functions to exit normally, so no error reaches your pcall. You'll need to use loadstring and set the environment correctly for the returned function, then pcall that (just like os.run does) if you want to catch the error yourself.
TheJebForge #3
Posted 07 October 2014 - 06:31 PM
Then, how to get error from os.run?
Lyqyd #4
Posted 07 October 2014 - 07:18 PM
Again, you wouldn't. You'd have to use loadstring, set the environment for the returned function, then pcall that function.
TheJebForge #5
Posted 07 October 2014 - 07:58 PM
PCall function is useless in my case (and i dont like to use it, and I dont understand what does loadstring is)! I fixd my Error Catcher by getting success from shell.run and If it not successful, in bsod, it runs programm one more time to print error!

Your fix is too difficult for me…
Edited on 07 October 2014 - 06:08 PM
KingofGamesYami #6
Posted 07 October 2014 - 09:13 PM
loadstring is really very easy.


local file = fs.open( "file_to_run", "r" )
local data = file.readAll()
file.close()
local func, err = loadstring( data )
if func then
  pcall( func )
else
  print( err )
end
Lyqyd #7
Posted 07 October 2014 - 11:18 PM
Yep, just throw a setfenv(func, setmetatable({shell = shell, multishell = multishell}, {__index = _G})) just before the pcall and catch the success/error returns from the pcall, then move the error handling to after the if rather than being an alternate branch. The "fix" OP is using is really quite broken, since it would only work for compile-time errors, and would fail/be very confusing for non-immediate runtime errors.
ElvishJerricco #8
Posted 07 October 2014 - 11:36 PM
loadfile should probably be mentioned. It's just like loadstring except you give it a file instead of code.

local function runShellProgramWithErrors(program, ...)
    local path = shell.resolveProgram(program)
    return assert(loadfile(path))(...)
end

local ok, err = pcall(runShellProgramWithErrors, "your_program", "arg1", ...)