[SERVER-11762] ProgressMeter is not thread-safe Created: 18/Nov/13 Updated: 13/Oct/21 Resolved: 02/Dec/13 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | Admin, Stability |
| Affects Version/s: | 2.5.4 |
| Fix Version/s: | 2.5.5 |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Matt Kangas | Assignee: | Matt Dannenberg |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||||||
| Backwards Compatibility: | Fully Compatible | ||||||||||||||||
| Operating System: | ALL | ||||||||||||||||
| Participants: | |||||||||||||||||
| Description |
|
[ed: original title "'out of memory, printing stack and exiting' during parallel/basic.js on Linux 64-bit DEBUG"] ProgressMeter is not thread-safe. Because of this, it is possible to crash the server when calling db.currentOp() during a map-reduce or index build. Threads are permitted to call CurOp::setMessage() on CurOp objects they own. CurOp::setMessage() calls ProgressMeter::setName(), which calls operator= ProgressMeter::_name, which is an std::string. db.currentOp() calls CurOp::info() on CurOp objects owned by other threads. CurOp::info() calls ProgressMeter::toString(), which performs a copy on the same string above. Doing so while _name is being modified can result in a string with a corrupt length, which can crash the server (e.g. during allocation of a copy, or while reading unmapped memory). |
| Comments |
| Comment by Matt Dannenberg [ 02/Dec/13 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Author: {u'username': u'dannenberg', u'name': u'matt dannenberg', u'email': u'matt.dannenberg@10gen.com'}Message: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by J Rassi [ 18/Nov/13 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
The following parallel failure exhibits this scenario (evalc.js runs "for ( i=0; i<50000; i++ ){ db.currentOp(); }", while extent2.js runs "for ( i=0; i<100; i++ ) { [...] t.ensureIndex({x:1}); t.drop(); }") 2013/11/18: ffd52e5f46cf Linux 64-bit DEBUG parallel : basic.js http://buildlogs.mongodb.org/mci_0.9_linux_64_debug/builds/16259/test/parallel_0/basic.js
Demangled stack trace:
|