summaryrefslogtreecommitdiff
path: root/camera
diff options
context:
space:
mode:
authorEmilian Peev <epeev@google.com>2017-06-26 14:28:31 -0700
committerEmilian Peev <epeev@google.com>2017-06-30 00:41:09 +0000
commite06ed957c8c83bfa96fafa1e4a0355adaf14718b (patch)
tree1c5e4f360c8c2a5169be45cea9b512e5c7b09f1d /camera
parent54c6fafa92ebddec1c6d5e9da4e360b22578f661 (diff)
QCamera3: Avoid possible deadlock when reporting failed buffers
"QCamera3YUVChannel::streamCbRoutine" will acquire "mOfflinePpLock" before calling the channel error callback. The current callback implementation will also try to acquire "mMutex". This could trigger a deadlock in case a request for the YUV channel is also currently executing. The request will acquire "mMutex" first and then try to lock "mOfflinePpLock". Bug: 63002361 Test: Complete Camera/Camera2 CTS. Change-Id: I2877aebf94c5a15b6742548bcbd1d1c4adc5e9d2
Diffstat (limited to 'camera')
-rw-r--r--camera/QCamera2/HAL3/QCamera3Channel.cpp86
1 files changed, 46 insertions, 40 deletions
diff --git a/camera/QCamera2/HAL3/QCamera3Channel.cpp b/camera/QCamera2/HAL3/QCamera3Channel.cpp
index e14442e7..8bd1deb4 100644
--- a/camera/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/camera/QCamera2/HAL3/QCamera3Channel.cpp
@@ -2839,56 +2839,62 @@ void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
}
if (mBypass) {
- List<PpInfo>::iterator ppInfo;
-
- Mutex::Autolock lock(mOfflinePpLock);
- resultFrameNumber = mMemory.getFrameNumber(frameIndex);
- for (ppInfo = mOfflinePpInfoList.begin();
- ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
- if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
- break;
- }
- }
- LOGD("frame index %d, frame number %d", frameIndex, resultFrameNumber);
- //check the reprocessing required flag against the frame number
- if (ppInfo == mOfflinePpInfoList.end()) {
- LOGE("Error, request for frame number is a reprocess.");
- stream->bufDone(frameIndex);
- return;
- }
-
- if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
- mChannelCbBufErr(this, resultFrameNumber,
- CAMERA3_BUFFER_STATUS_ERROR, mUserData);
- }
+ {
+ List<PpInfo>::iterator ppInfo;
- if (ppInfo->offlinePpFlag) {
- mm_camera_super_buf_t *frame =
- (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
- if (frame == NULL) {
- LOGE("Error allocating memory to save received_frame structure.");
- if(stream) {
- stream->bufDone(frameIndex);
+ Mutex::Autolock lock(mOfflinePpLock);
+ resultFrameNumber = mMemory.getFrameNumber(frameIndex);
+ for (ppInfo = mOfflinePpInfoList.begin();
+ ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
+ if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
+ break;
}
+ }
+ LOGD("frame index %d, frame number %d", frameIndex,
+ resultFrameNumber);
+ //check the reprocessing required flag against the frame number
+ if (ppInfo == mOfflinePpInfoList.end()) {
+ LOGE("Error, request for frame number is a reprocess.");
+ stream->bufDone(frameIndex);
return;
}
- *frame = *super_frame;
- m_postprocessor.processData(frame, ppInfo->output, resultFrameNumber);
- free(super_frame);
- return;
- } else {
- if (ppInfo != mOfflinePpInfoList.begin()) {
- // There is pending reprocess buffer, cache current buffer
- if (ppInfo->callback_buffer != NULL) {
- LOGE("Fatal: cached callback_buffer is already present");
+ if (ppInfo->offlinePpFlag) {
+ mm_camera_super_buf_t *frame =
+ (mm_camera_super_buf_t *)malloc(sizeof(
+ mm_camera_super_buf_t));
+ if (frame == NULL) {
+ LOGE("Error allocating memory to save received_frame structure.");
+ if(stream) {
+ stream->bufDone(frameIndex);
+ }
+ return;
}
- ppInfo->callback_buffer = super_frame;
+
+ *frame = *super_frame;
+ m_postprocessor.processData(frame, ppInfo->output,
+ resultFrameNumber);
+ free(super_frame);
return;
} else {
- mOfflinePpInfoList.erase(ppInfo);
+ if (ppInfo != mOfflinePpInfoList.begin()) {
+ // There is pending reprocess buffer, cache current buffer
+ if (ppInfo->callback_buffer != NULL) {
+ LOGE("Fatal: cached callback_buffer is already present");
+ }
+ ppInfo->callback_buffer = super_frame;
+ return;
+ } else {
+ mOfflinePpInfoList.erase(ppInfo);
+ }
}
}
+
+ if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
+ mChannelCbBufErr(this, resultFrameNumber,
+ CAMERA3_BUFFER_STATUS_ERROR, mUserData);
+ }
+
}
QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);