Dynamic Analysis of Concurrent Programs

Dynamic analysis of concurrent programs aims at coping with the inherent non-determinism in scheduling concurrent threads (processes or other units of computation) due to which it is difficult to catch rarely occurring but often critical bugs in synchronisation. To counter the problem, approaches such as extrapolating checkers, systematic exploration of all schedules up to some bound, and/or noise injection are used.
To find errors in synchronisation of concurrently executing threads, processes, or any other concurrently executing tasks.

Computing platforms with many CPUs and/or CPU cores are omnipresent nowadays. This holds even for embedded systems. In order to fully benefit from such architectures, concurrent programming is necessary. However, programming concurrent applications is significantly harder than producing sequential code since one additionally needs to properly synchronise all the concurrently running tasks. Improper synchronisation often leads to errors (such as data races, deadlocks, atomicity violations, order violations, etc.) that can have disastrous consequences but that are extremely difficult to detect. The reason is that such errors can manifest extremely rarely, and it is thus very difficult to catch them by traditional testing.

At the same time, concurrency is a very significant obstacle for current analysis and verification methods too. Methods of lightweight static analysis often suffer from quite significant imprecision on concurrent code despite a lot of effort has been invested and is still being invested into their improvement in this area. Model checking can in theory provide a guarantee that all such errors will be discovered in a precise way, but it suffers from scalability issues on large systems, and it may also have problems with various features of real-life code (user inputs, network communication, dealing with file systems and databases, etc.). Various forms of bounded model checking or systematic testing of concurrent code [DAC1, DAC2] improve the scalability but still suffer from similar issues.

An alternative to the above approaches is dynamic analysis (performed at runtime during testing runs or even during production runs) that not only monitors the activity of the system under test but tries to extrapolate the behaviour seen in the testing runs and to produce warnings about possible errors in the system even though such errors have not been witnessed in the performed runs. Various specialised checkers, e.g., [DAC5, DAC6, DAC7, DAC8, DAC9, DAC10], capable to produce such warnings have been developed for different kinds of concurrency errors, such as data races, deadlocks, atomicity violations, or breakage of so-called contracts for concurrency, which can encode numerous more specific kinds of concurrency errors (atomicity violation, order violation, etc.).

These approaches cannot guarantee overall soundness: they can at most guarantee soundness wrt the witnessed testing runs – this is, they can guarantee that if symptoms of an error appear in these runs, a warning will be produced. On the other hand, they can be more scalable and can cope better with various features of real-life code than model checking and can avoid various sources of false alarms that are problematic for static analysis (such as which memory objects are available to which threads at which moment).

Moreover, the effectiveness of extrapolating dynamic analyses can be further improved by combining them with so-called noise injection methods [DAC3, DAC4]. Such methods try to disturb the scheduling of concurrently executing threads (e.g., by injecting context switches, delays, etc. into the execution) such that thread interleavings that are otherwise rare manifest more often. (Note that the produced interleavings are still valid – unless real-time features are in play.) With noise injection, one can sometimes even use precise checkers (i.e., without any extrapolation and hence with no false alarms) and still can catch very rare behaviours even in industrial applications [DAC11].

  • Ability to detect even rarely manifesting concurrency-related errors.
  • Better scalability than various heavier-weight formal methods or their bounded variants.
  • Better handling of various not purely computational features of real-life systems (inputs, network connection, database connections, etc.).
  • Can better avoid many false alarms hard to avoid in light-weight static analysis approaches.
  • Does not provide formal soundness guarantees.
  • When using extrapolation, false alarms may arise.
  • Some of the efficient extrapolating analyses are highly specialised in the considered class of errors.
  • Monitoring of the running system and noise injection can slow-down the application significantly.
  • Needs the system to be verified in a runnable form, including a test harness (unless the system is operated and monitored in production).
  • Noise injection can invalidate real-time features of a system.

[DAC1] Musuvathi, M., Qadeer, S., Ball, T., Basler, G., Nainar, P., Neamtiu, I.: Finding and Reproducing Heisenbugs in Concurrent Programs. Proc. of OSDI’08, USENIX, 2008.

[DAC2] Wu, J., Tang, Y., Hu, H., Cui, H., Yang, J.: Sound and Precise Analysis of Parallel Programs through Schedule Specialization. Proc. of PLDI’12, ACM, 2012.

[DAC3] Edelstein, O., Farchi, E., Goldin, E., Nir, Y., Ratsaby, G., Ur, S.: Framework for Testing Multi-threaded JavaPrograms. Concurrency and Computation: Practice and Experience 15(3-5), 2003.

[DAC4] Fiedor, J., Hruba, V., Krena, B., Letko, Z., Ur, S., Vojnar, T.: Advances in Noise-based Testing of Concurrent Software. Software Testing, Verification, and Reliability 25(3), 2015.

[DAC5] Hammer, C., Dolby, J., Vaziri, M., Tip, F.: Dynamic Detection of Atomic-Set-Serializability Violations. Proc. of ICSE’08, ACM, 2008.

[DAC6] Flanagan, C., Freund, S., Yi, J.: Velodrome: A Sound and Complete Dynamic Atomicity Checker for Multithreaded Programs. Proc. of PLDI’08, ACM, 2008.

[DAC7] Joshi, P., Park, C.S., Sen, K., Naik, M.: A Randomized Dynamic Program Analysis Technique for Detecting Real Deadlocks. Proc. of PLDI’09, ACM, 2009.

[DAC8] Flanagan, C., Freund, S.: FastTrack: Efficient and Precise Dynamic Race Detection. Proc. of PLDI’09, ACM, 2009.

[DAC9] Rhodes, D., Flanagan, C., Freund, S.N.: BigFoot: Static Check Placement for Dynamic Race Detection. Proc. of PLDI’17, ACM, 2017.

[DAC10] Dias, R., Ferreira, C., Fiedor, J., Lourenco, J., Smrcka, A., Sousa, D., Vojnar, T.: Verifying Concurrent Programs Using Contracts. Proc. of ICST’17, IEEE, 2017.

[DAC11] Fiedor, J., Muzikovska, M., Smrcka, A., Vasicek, O., Vojnar, T.: Advances in the ANaConDA Framework for Dynamic Analysis and Testing of Concurrent C/C++ Programs. Proc. of ISSTA’18, ACM, 2018.

Method Dimensions
In-the-lab environment
Experimental - Monitoring
Software
Implementation
Thinking, Acting
Non-Functional - Safety, Functional
V&V process criteria, SCP criteria
Relations
Contents

There are currently no items in this folder.