Avoiding concurrency defects in Go programming
The Go programming language is a relatively new language designed for performance on multicore systems, ease of programming, and reliability. Go’s design is heavily influenced by the C family of languages in its basic syntax, use of static typing and compilation. But Go adds automatic memory management - borrowed from the Modula-3 and Java family of languages, lightweight threads called “Goroutines”, and “channels” borrowed from Occam (which in turn borrowed from CSP).
“Channels” are “Goroutines” are intended to help the programmer with data-structures held in shared memory and accessed by multiple threads - typically a common source of concurrency defects as described in our recent Concurrency Defect Resolution Best Practices technical paper. The programmer is encouraged to “share memory by communicating” over a channel, rather than using traditional concurrency techniques such as mutexes and semaphores.
A recent paper, Understanding Real-World Concurrency Bugs in Go, attempts to quantify how successful Go’s channels and Goroutines have been in helping programmers avoid concurrency defects. The paper’s authors analyze a number of concurrency defects in well-used open source projects.
To summarise, the results are somewhat disappointing. The paper’s authors find defects due to misunderstanding and misuse of channels, the improper mixing of channels and more traditional techniques, and the inadequacy of existing tooling. They conclude that, in practice, the use of channels “does not necessarily make multithreaded programs less error-prone” than using traditional techniques.
Introducing LiveRecorder for Go programs
LiveRecorder from Undo accelerates software defect resolution across all phases of your software lifecycle, by eliminating the guesswork in defect diagnosis.
How does it do this?
LiveRecorder records a failing process down to instruction level - capturing bugs in the act. The recording represents a 100% reproducible test case. Engineers can then replay the recording artifact forwards & backwards - providing full visibility and data-driven insight into what their software really did before it failed or misbehaved.
On top of reducing time-to-resolution of software defects, LiveRecorder captures intermittent, non-deterministic failures that cannot be caught any other way.
A few months ago, we asked ourselves a question: does LiveRecorder support the Go language?
LiveRecorder has always been able to record the execution history of Go applications as they fail. But up until recently, LiveRecorder’s ability to replay the recording to debug Go applications was on a par with gdb’s - namely a very basic level of support, with no understanding of Go’s channels or Goroutines.
The Go ecosystem looks different from C/C++ software programming: the Golang community prefers the Delve command-line debugger and IDEs such as JetBrains’ GoLand and Microsoft’s Visual Studio Code (which use Delve under-the-hood). So we decided to start by adding support for:
- loading LiveRecorder recordings into Delve;
- and adding the forward and reverse-debugging functionality to get full visibility into what the program did and why.
Most developers prefer to work in an IDE instead of a command-line. At Undo we’re most familiar with JetBrains’ family of IDEs through our integration of LiveRecorder with CLion for C/C++ (and forthcoming integration with IntelliJ for Java). So JetBrains’ GoLand IDE was an obvious choice. LiveRecorder 5.2 integration with GoLand is documented here.
Finally, we wanted to expose LiveRecorder’s ability to let applications record themselves programmatically. This work is now published in our Go bindings for our “undolr” library.
The future of debugging Go software
Support for Delve currently resides in a fork on github. We hope to upstream this work into the main Delve project, and to build on it to expose more LiveRecorder functionality in Delve.
We also intend to expose more LiveRecorder functionality in GoLand - e.g. support for “bookmarks”, jumping to the start or end of recordings, etc.
Further forward, we would like to integrate with other IDEs - in particular Microsoft’s Visual Studio Code.
See LiveRecorder for Go in action
Are you developing enterprise software? Want to see how LiveRecorder can help you resolve software defects faster (in your test suite or in production)? Just book a demo and we’ll be happy to show you.
Catch intermittent bugs in the actCan't reproduce a non-deterministic bug? This on-demand webinar illustrates how to obtain a 100% reproducible test case.Watch the webinar
Concurrency Defects ResolutionNew techniques to help quickly find and resolve defects in multithreaded and multiprocess applicationsDownload the technical paper