Using a C level debugger in Rstudio

I often use C level debuggers such as lldb and gdb when debugging R packages with compiled code. If you are unfamiliar with doing this Kevin Ushey has an excellent post on the topic. Usually bugs are reproducible both from the R terminal and RStudio. If this is the case then running R under the debugger is easy; just start R from the terminal with R -d lldb.

However more rarely there will be a bug that only occurs when the code is run in RStudio, and in these cases you would ideally like to be able to attach to the internal RStudio Rsession process.

You can get the PID (process identifier) of any R process by calling Sys.getpid() from the R console. Then you can have the debugger attach to this PID with the -p argument to lldb, e.g. lldb -p 45323. However if you do this with the current RStudio release (v1.1) you will get this!

I believe this occurs because of how RStudio detects if the R process is still running. When the debugger interrupts internal rsession process RStudio no longer thinks it has an active R session running, so shows the error message.

However you can work around this by using a feature of lldb I hadn’t used until encountering this problem, --waitfor. This allows you to have lldb attach to a process (by name) as soon as it starts.

To do this first start lldb from a separate console (lldb). This will launch you into the lldb prompt. Then tell lldb you would like to attach to the rsession process using --waitfor.

process attach --name rsession --waitfor

lldb will then wait for this rsession process to start. Now we can start up RStudio. The lldb session will then print something like the following

Process 50879 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x000000010085b4f8 rsession`rstudio_boost::filesystem::path::path<char const*>(char const*, char const*) + 88
rsession`rstudio_boost::filesystem::path::path<char const*>:
->  0x10085b4f8 <+88>: movb   %al, (%r13)
    0x10085b4fc <+92>: jmp    0x10085b50c               ; <+108>
    0x10085b4fe <+94>: movq   %r13, %rdi
    0x10085b501 <+97>: movq   %r12, %rsi
Target 0: (rsession) stopped.

And the RStudio session will be stopped with RStudio only partially loaded. You can then continue execution in lldb with c and the RStudio session will continue to load. From here you can set breakpoints / interrupt execution as you normally would when debugging with lldb.

While this process isn’t too cumbersome, it is certainly more work than is ideal, and the workaround is somewhat esoteric. Luckily, RStudio 1.2+ (now available as a preview release) makes this extra workaround unnecessary! In v1.2 you can attach lldb directly to a running RStudio session without causing RStudio to fail!

Thanks again to Jonathan McPherson and Kevin Ushey for their pointers on how get this working for RStudio 1.1.

Avatar
Jim Hester
Software Engineer

I’m a Senior Software Engineer at Netflix and R package developer.

Related