From: José Fonseca Date: Thu, 11 Apr 2013 17:54:06 +0000 (+0100) Subject: gui: Handle calls stranded between frames gracefully (issue #117). X-Git-Url: https://git.cworth.org/git?p=apitrace;a=commitdiff_plain;h=caa8428eb4c4292d3ea53405d4dc9c3c3f21f10a gui: Handle calls stranded between frames gracefully (issue #117). Still a bit hackish (those calls will disappear), but at least the gui doesn't crash now. --- diff --git a/common/trace_model.hpp b/common/trace_model.hpp index bb8936e..9558225 100644 --- a/common/trace_model.hpp +++ b/common/trace_model.hpp @@ -469,7 +469,7 @@ public: CallFlags flags; - Call(FunctionSig *_sig, const CallFlags &_flags, unsigned _thread_id) : + Call(const FunctionSig *_sig, const CallFlags &_flags, unsigned _thread_id) : thread_id(_thread_id), sig(_sig), args(_sig->num_args), diff --git a/common/trace_parser.cpp b/common/trace_parser.cpp index 095af67..c70517e 100644 --- a/common/trace_parser.cpp +++ b/common/trace_parser.cpp @@ -187,8 +187,11 @@ Call *Parser::parse_call(Mode mode) { std::cerr << "\tLEAVE\n"; #endif call = parse_leave(mode); - adjust_call_flags(call); - return call; + if (call) { + adjust_call_flags(call); + return call; + } + break; default: std::cerr << "error: unknown event " << c << "\n"; exit(1); @@ -456,6 +459,14 @@ Call *Parser::parse_leave(Mode mode) { } } if (!call) { + /* This might happen on random access, when an asynchronous call is stranded + * between two frames. We won't return this call, but we still need to skip + * over its data. + */ + const FunctionSig sig = {0, NULL, 0, NULL}; + call = new Call(&sig, 0, 0); + parse_call_details(call, SCAN); + delete call; return NULL; } diff --git a/gui/apitrace.cpp b/gui/apitrace.cpp index a69ce2f..671fc68 100644 --- a/gui/apitrace.cpp +++ b/gui/apitrace.cpp @@ -266,7 +266,7 @@ void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame, const QVector &calls, quint64 binaryDataSize) { - Q_ASSERT(frame->numChildrenToLoad() == calls.size()); + Q_ASSERT(frame->numChildrenToLoad() >= calls.size()); if (!frame->isLoaded()) { emit beginLoadingFrame(frame, calls.size()); diff --git a/gui/traceloader.cpp b/gui/traceloader.cpp index 2ad32b1..6110c59 100644 --- a/gui/traceloader.cpp +++ b/gui/traceloader.cpp @@ -410,8 +410,9 @@ TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame) ApiTraceCall *apiCall = apiCallFromTraceCall(call, m_helpHash, currentFrame, this); - calls[parsedCalls] = apiCall; - Q_ASSERT(calls[parsedCalls]); + Q_ASSERT(apiCall); + Q_ASSERT(parsedCalls < calls.size()); + calls[parsedCalls++] = apiCall; if (apiCall->hasBinaryData()) { QByteArray data = apiCall->arguments()[ @@ -419,8 +420,6 @@ TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame) binaryDataSize += data.size(); } - ++parsedCalls; - delete call; if (apiCall->flags() & trace::CALL_FLAG_END_FRAME) { @@ -428,11 +427,14 @@ TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame) } } - assert(parsedCalls == numOfCalls); - Q_ASSERT(parsedCalls == calls.size()); + // There can be fewer parsed calls when call in different + // threads cross the frame boundary + Q_ASSERT(parsedCalls <= numOfCalls); + Q_ASSERT(parsedCalls <= calls.size()); + calls.resize(parsedCalls); calls.squeeze(); - Q_ASSERT(parsedCalls == currentFrame->numChildrenToLoad()); + Q_ASSERT(parsedCalls <= currentFrame->numChildrenToLoad()); emit frameContentsLoaded(currentFrame, calls, binaryDataSize); return calls; @@ -469,8 +471,9 @@ void TraceLoader::findCallIndex(int index) call = *itr; } } - Q_ASSERT(call); - emit foundCallIndex(call); + if (call) { + emit foundCallIndex(call); + } } void TraceLoader::search(const ApiTrace::SearchRequest &request)