How to debug programs without IDE

  1. 7 months ago

    I'm trying to set up a toolchain using batch files and Sublime Text. As such, it would be nice to be able to link the debugger that the IDE uses to a running program, so I can read the error (and maybe debug?) messages from my code. Is this possible? How?

  2. fodinabor

    25 Jun 2016 Administrator

    hmm.. I am not sure whether that will work.. but I'll explain to you, how debugging works at the moment:

    1. The Player connects to the IDE via UDP
    2. the player sends error (or print()) messages to the IDE via UDP
    3. the IDE uses this information to show the trace back.

    so you see there's no real debugging with breakpoints and such - and you would need UDP support to get the traceback informations
    some info how the stuff is sent: https://github.com/ivansafrin/Polycode/blob/master/Player/Contents/Source/PolycodePlayer.cpp#L32

  3. Hmm... Okay. I think I'll try and make a debugger application with Love2D and LuaSocket. Is there any reason that wouldn't work?

    On a side note, does this mean that every Polycode application uses port 4630 on the loopback address?

  4. Using Sublime Text myself, I would be very interested in a debugger with breakpoints. I've figured though that when you run your application, a popup console with errors for debugging, print outputs etc.. can be opened. The shortcut on mac is "shift + cmd + /" I don't know on windows, but I assume it's available there too.

  5. Edited 7 months ago by Arkathorn

    As there are some notable features (namely networking) that are only available to the C++ API, I've decided to start developing that way instead. I'll post my findings thus so far on the debugging protocol, and I may return to the project on a future date.

    Firstly, there was absolutely no need to develop such a program using Love2D, and I was only doing so because I had some libraries built up in it. It is far more practical to simply use a Lua program, parsed by some simple C++.

    The protocol is completely accessible to standard UDP libraries (such as LuaSocket, which I used), and is bound to "127.0.0.1:4630".

    Upon startup, a Polycode program begins to broadcast pings every second. These pings differ only by a single byte, which counts what number ping it is (not the number of seconds elapsed).

    When a print statement is executed, or an error occurs, it is added to a list of packets sent every cycle (one second). These packets are all sent simultaneously, but in order.

    Example:

    print("This is the first print statement.")
    print("This is the second print statement.")

    After the first three or so pings (the time it takes to initialize the program, at least on my computer), this sequence will be sent every second:

    Print Statement 1
    Print Statement 2
    Ping

    When an uncaught error occurs, a similar process transpires. Packets will continue being sent, even though program execution has halted, until the application is closed.

    I have not yet analysed the print statement packets, but my analysis of the error packets follows:

    Errors queue two packets: The error and the backtrace.

    The error packet contains at least three relevant data points: The line the error occurred on, the message the error returned, and the file the error occurred in. It may also contain the length of the backtrace, but this is unconfirmed.

    The line and message are a fixed length from the start of the datagram:

    The line number is the twenty-first (21st) byte in the datagram.
    The error message starts on the twenty-fifth (25th) byte, and is null-terminated (is immediately followed by a zero byte, which can be used to detect the length of the message).

    The file path is a bit trickier. The position of this data within the datagram is variable, so it must be detected by string operations. I used the following line to extract it:

    local file = data:match("%g*%.lua")

    Where 'data' is the datagram string.

    I have not yet analysed any of the rest of the protocol, but I have some additional insights.

    As the datagram contains unprintable characters, it cannot be printed. It should instead be passed to a function that translates all unprintable characters to a readable, unique format. This is the function I used:

    local function fixstring(str)
    	local ret = ""
    	for i=1,str:len() do
    		local c = str:sub(i,i)
    		if not c:find("[%w%p]") then
    			ret = ret.."_"..c:byte().."_"
    		else
    			ret = ret..c
    		end
    	end
    	return ret
    end

    Some errors (such as a 'require' error) will not pass the same text to the debugging protocol as they would to a console output. As a result these errors are entirely uninformative, so I advise finding some way to capture the true error using 'pcall' and/or 'xpcall' (There is also a character limit on the print messages sent to the protocol, so you may need to separate the error into smaller strings.).

 

or Sign Up to reply!