ZeroBrane
By seeking, you will discover...
Subscribe
12 MAY 2014
ZeroBrane Studio has already been used to debug various Lua engines -- game frameworks (like Corona, Gideros, Moai, Love2d), home automation devices, wireshark scripts, Adobe Lightroom plugins, and more -- but there have been several Lua environments that I haven't tried it on. One of them is OpenResty/Nginx Lua scripts. OpenResty is a web application server built around nginx, a very fast web server, that provides non-blocking IO with various backends (Redis, Memcached, MySQL, HTTP servers, and others) and supports Lua as its scripting language.
I first tried to use the non-blocking socket API that OpenResty provides, but couldn't get the debugging to work because socket calls that were supposed to be blocking were returning too early, which was breaking the interaction between the debugger in the application and the IDE. Based on advice from Yichun Zhang (agentzh), the maintainer of the OpenResty bundle, I then tried to use the same luasocket library that ZeroBrane Studio is using and got it all working. These are the steps you can follow to try it yourself:
1. Get ZeroBrane Studio. These instructions are for Windows, but the debugging should work on Linux and OSX as well.
2. Start ZBS (zbstudio.exe
or zbstudio.sh
) and start the debugger Project | Start Debugger Server
.
1. I'm using a very basic config (<NGINX>/conf/nginx.conf
):
worker_processes 1; events { worker_connections 1024; } http { lua_package_path '<ZBS>/lualibs/?/?.lua;<ZBS>/lualibs/?.lua;;'; lua_package_cpath '<ZBS>/bin/clibs/?.dll;;'; server { location /hellolua { default_type 'text/plain'; content_by_lua_file 'lua/content.lua'; } } }
Make sure you replace <ZBS>
with the actual path to ZeroBrane Studio location. If you are running on OSX, replace ?.dll
with ?.dylib
and if you are running on Linux, replace bin/clibs/?.dll
with either bin/linux/x86/clibs/?.so
or bin/linux/x64/clibs/?.so
depending on your platform.
2. Create the file we are going to debug (<NGINX>/lua/content.lua
), which may look like this:
require('mobdebug').start('192.168.1.22') local name = ngx.var.arg_name or "Anonymous" ngx.say("Hello, ", name, "!") ngx.say("Done debugging.") require('mobdebug').done()
Note that start()
call takes the IP of the computer running the IDE. It uses "localhost" by default, but since your nginx instance is running there, you will need to specify the IP address of the computer running the IDE (in my case it is 192.168.1.22
).
3. Open this file (<NGINX>/lua/content.lua
) file in the IDE and set the project directory to lua
folder by going to Project | Project Directory | Set From Current File
.
Now start nginx and go to http://localhost/hellolua. If everything is right, you should see ZeroBrane Studio activated with the green arrow pointing to the second line (similar to what can be seen in the screenshot above). You can now set breakpoints, step through the code, look at the stack and so on.
You can also go to the remote console and run any ngx command there. For example, if you run ngx.say("Message from console")
(as shown in the screenshot), you will see this text in the output after the script is done.
If you get "attempt to yield across C-call boundary" error in Nginx logs when you start debugging, try with a more recent ZeroBrane Studio (0.70+) as it includes several improvements that make debugging to work with recent versions of OpenResty.
The following steps are only needed if you configure OpenResty/Nginx for remote debugging when Nginx runs on one machine and ZeroBrane Studio runs on another one. When you run both on the same machine, Nginx is using modules included with ZeroBrane Studio as those are referenced by lua_package_path
and lua_package_cpath
directives.
1. Copy the debugger (mobdebug.lua
) and socket files. Go to <ZBS>/lualibs/mobdebug/
and copy mobdebug.lua
to<NGINX>/lua/mobdebug.lua
; also copy <ZBS>/lualibs/socket.lua
to <NGINX>/lua/
. After all this is done, the content of lua
folder is going to look like this:
./ content.lua mobdebug.lua socket.lua
2. Copy <ZBS>/bin/clibs/socket/core.dll
to <NGINX>/socket/core.dll
(core.dylib
and core.so
files are in the bin
folder as well).
You should get a copy of my slick ZeroBrane Studio IDE and follow me on twitter here.
Posted by Paul Kulchenko on Monday, May 12, 2014 at 9:22 PM
Filed in zerobrane | Tagged ide, lua, nginx, openresty, zerobrane
Jul 9 2014ZeroBrane Studio in black0
Jun 21 2014Moonscript debugging with ZeroBrane Studio0
Jun 17 2014Lapis debugging with ZeroBrane Studio0
Apr 6 2014Debugging Adobe Lightroom plugins with ZeroBrane Studio2
Mar 19 2014Corona on-device debugging with ZeroBrane Studio0
Feb 28 2014Gideros on-device debugging with ZeroBrane Studio0
Dec 7 2013Saving debugging output to a file0
Dec 3 2013Lua package managers and integration with ZeroBrane Studio2
Nov 29 2013Remote file editing while debugging0
Nov 27 2013Debugging on Vera devices with ZeroBrane Studio0
Sep 26 2013Real-time watches with ZeroBrane Studio1
Sep 10 2013ZeroBrane Studio LuaJIT, Lua5.2 and luasocket changes0
Sep 8 2013Clone view plugin for ZeroBrane Studio0
Jul 25 2013Cocos2d-x simulator and on-device debugging with ZeroBrane Studio7
Jul 23 2013ZeroBrane Studio Bug Bounty2
Jul 22 2013ZeroBrane Studio in seven languages0
Jun 22 2013Scope aware variable indicators4
Jun 14 2013Debugging embedded code fragments0
Feb 11 2013Marmalade Quick debugging with ZeroBrane Studio8
Feb 10 2013Debugging and live coding with Corona SDK11
Jan 14 2013Fixing malformed UTF-8 in Lua0
Dec 27 2012Getting started and FAQ for ZeroBrane Studio0
Dec 27 2012Gideros live coding: a simple example1
Dec 10 2012ZeroBrane Studio is one year old7
Dec 10 2012GSL-shell script debugging0
Nov 20 2012Live coding with Moai16
Nov 20 2012ZeroBrane Studio in Zenburn and Tomorrow colors13
Nov 7 2012ZeroBrane Studio in your language0
Nov 5 2012Debugging Wireshark Lua scripts2
Oct 30 2012Tragedy of the Commons and open source projects14
Oct 23 2012Amazon Payments doesn't support "pay-what-you-want" models1
Oct 11 2012Gideros live coding with ZeroBrane Studio10
Oct 8 2012Gideros debugging with ZeroBrane Studio9
Oct 2 2012500 downloads in 30 days4
Sep 19 2012Packaging ZeroBrane Studio as OSX app0
Sep 6 2012Moai debugging with ZeroBrane Studio26
Aug 21 2012Live coding with Löve0
Jun 28 2012Löve debugging with ZeroBrane Studio12
Jun 12 2012Alphanum sorting for humans in Lua0
Jun 2 2012Serpent: Lua serializer and pretty printer3
May 31 2012Live coding in Lua with ZeroBrane Studio4
May 28 2012The 'Flame' malware using Lua?0
Apr 22 2012Working with Gist API from Lua0
Apr 10 2012HTTPS/SSL calls with Lua and LuaSec9
Mar 31 2012Dynamic execution of embedded gists0
Mar 25 2012Lua: Good, bad, and ugly parts26
Mar 20 2012Can Lua be faster than JavaScript in a browser?0
Mar 16 2012Drawing on browser canvas with Lua2
Jan 20 2012Drawing outside of OnPaint with wxWidgets0
Jan 18 2012Drawing trees with turtles0
Dec 18 2011Lua beautifier in 55 lines of Perl3
Hi Paul, I've tried debugging in linux as your guide, but could not make it work. After I made a request to http://localhost/hellolua, I got an error log in nginx's error.log, "[error] 23503#0: *22 lua entry thread aborted: runtime error: attempt to yield across C-call boundary" and nginx ended the request with a "500 Internal Server Error" response. It seemed that the luasocket which mobdebug is using produced the error. I was using openresty-1.5.8(with the bunlded LuaJIT-2.1-20140109) and zbstudio-0.60 in SuSE Linux, I also tried in Ubuntu 12.10 using openresty-1.5.12 and zbstudio-0.60 and got the same error. Did I miss somthing? Any suggestion? Any help would be greatly appreciated!
LiuJun | June 10, 2014 7:28 PM | Reply
Hi LiuJun, I initially got the same error -- "attempt to yield across C-call boundary" -- and this is why I switched to using "blocking" luasocket, as this is needed for the debugger. Is it possible that in your case you use a nonblocking luasocket that comes with OpenResty?
Try removing references to "luapackagecpath" and replacing the content of content.lua with something like: "print(1) require 'socket' print(2)". This should fail if luasocket is indeed unavailable. If it does correctly reference the version from ZeroBrane Studio, I don't see why it would fail, but I haven't tested it on Linux. I'll try to set it up on my VM to see if I can reproduce this issue.
Paul Kulchenko replied to comment from LiuJun | June 10, 2014 9:36 PM | Reply
I removed the zbstudio's clibs path from lua_package_cpath as you suggested, and got the following error when require "socket":
"[error] 10473#0: *29 lua entry thread aborted: runtime error: /opt/zbstudio/lualibs/socket.lua:12: module 'socket.core' not found:"
So I think the lua script was using luasocket from zbstudio, not from openresty.
LiuJun | June 11, 2014 3:11 AM | Reply
LiuJun, you seem to be doing everything correctly and the results are as expected. I'll have to try it myself on Linux to see what may be going on (in a day or two).
Paul Kulchenko replied to comment from LiuJun | June 11, 2014 10:44 PM | Reply
LiuJun, I can confirm the same issue. I tried on Ubuntu 12.04 using the latest OpenResty (1.7.0.1) and got the same error. I don't have a good explanation for you and am working on a test case. Drop me an email (my address is at the bottom of the page) and I'll send you an update when I figure out what may be going on. Paul.
Paul Kulchenko replied to comment from LiuJun | June 14, 2014 4:06 PM | Reply
LiuJun, you need to add "coroutine = require('coroutine')" before "start()" call. It seems like openresty on Linux is using "lightweight threads" instead of "default" coroutines and those interfere with debugging as they are managed by ngx_lua. Paul.
Paul Kulchenko replied to comment from LiuJun | June 15, 2014 10:10 AM | Reply
It works smoothly now. Thank you very much.
LiuJun replied to comment from Paul Kulchenko | June 16, 2014 9:26 PM | Reply
LiuJun, glad it's working for you. The workaround I suggested earlier is likely not to work in the coming version of OpenResty. This issue should be fixed in the current master branch of ZeroBrane Studio; please check that version as it uses updated debugger, which doesn't require any workarounds.
Paul Kulchenko replied to comment from LiuJun | June 17, 2014 9:18 PM | Reply
Hi Paul, I'm trying to get the remote debugging going and seem to have trouble getting the two boxes to communicate. The actual server is an AWS Ubuntu box and the studio is running locally on my windows machine. Essentially, it looks like the script simply gives up a few minutes after I refresh the page (displays the following without ever reaching the studio running on my machine): "Hello, Anonymous! Done debugging." Is there any specific port or range of ports I need to open up to get this going, do you know? Thank you very much!!
Ilya | August 9, 2014 12:16 PM | Reply
Hi Ilya, per our email exchange, you should make sure the (default) port 8172 is open on your computer running the IDE as this is the port that is used for debugging. Also make sure that "require('mobdebug').start('IP-address-of-ZBS')" call includes the IP address of the machine that runs ZeroBrane Studio. This should resolve the issue.
Paul Kulchenko replied to comment from Ilya | August 30, 2014 11:36 AM | Reply