Fix a data race in AudioEncoderMutableImpl and derived classes

Before this change, it could happen that a caller would get a pointer
to the encoder_ but not use it before another thread called the
Reconstruct method, changing the pointer. This of course resulted in
bad access crashes. With this change, each use of the pointer acquired
from the encoder() method is protected by the same lock that is
required to update the pointer. Note that this fix is probably too
aggressive, since it also affects the Opus implementation; the crash
has so far only been seen for iSAC.

Also adding a test to trigger the problem. The test did not trigger
the problem deterministically, but out would typically find it in less
than 1000 runs.

BUG=chromium:499468
R=jmarusic@webrtc.org, kwiberg@webrtc.org

Review URL: https://codereview.webrtc.org/1176303004.

Cr-Commit-Position: refs/heads/master@{#9436}
This commit is contained in:
Henrik Lundin
2015-06-15 13:46:15 +02:00
parent 05ce5dd0f1
commit a6aa6d96f8
6 changed files with 230 additions and 11 deletions

View File

@ -67,6 +67,7 @@ int AudioEncoderDecoderMutableIsacFix::Decode(const uint8_t* encoded,
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->Decode(encoded, encoded_len, sample_rate_hz,
max_decoded_bytes, decoded, speech_type);
}
@ -78,20 +79,24 @@ int AudioEncoderDecoderMutableIsacFix::DecodeRedundant(
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->DecodeRedundant(encoded, encoded_len, sample_rate_hz,
max_decoded_bytes, decoded, speech_type);
}
bool AudioEncoderDecoderMutableIsacFix::HasDecodePlc() const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->HasDecodePlc();
}
int AudioEncoderDecoderMutableIsacFix::DecodePlc(int num_frames,
int16_t* decoded) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->DecodePlc(num_frames, decoded);
}
int AudioEncoderDecoderMutableIsacFix::Init() {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->Init();
}
@ -101,32 +106,38 @@ int AudioEncoderDecoderMutableIsacFix::IncomingPacket(
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->IncomingPacket(payload, payload_len, rtp_sequence_number,
rtp_timestamp, arrival_timestamp);
}
int AudioEncoderDecoderMutableIsacFix::ErrorCode() {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->ErrorCode();
}
int AudioEncoderDecoderMutableIsacFix::PacketDuration(
const uint8_t* encoded,
size_t encoded_len) const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->PacketDuration(encoded, encoded_len);
}
int AudioEncoderDecoderMutableIsacFix::PacketDurationRedundant(
const uint8_t* encoded,
size_t encoded_len) const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->PacketDurationRedundant(encoded, encoded_len);
}
bool AudioEncoderDecoderMutableIsacFix::PacketHasFec(const uint8_t* encoded,
size_t encoded_len) const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->PacketHasFec(encoded, encoded_len);
}
size_t AudioEncoderDecoderMutableIsacFix::Channels() const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->Channels();
}