diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-13 23:20:40 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-13 23:20:40 +0000 |
commit | c35fd3740098ce9caa0bf035c8e9133fbf4ffa21 (patch) | |
tree | d614b9951d22bff488d5fc2e58593c35700452ab /chrome/browser/renderer_host | |
parent | 7995896e6b4d4d9c2d294fa76df89c143ef445af (diff) | |
download | chromium_src-c35fd3740098ce9caa0bf035c8e9133fbf4ffa21.zip chromium_src-c35fd3740098ce9caa0bf035c8e9133fbf4ffa21.tar.gz chromium_src-c35fd3740098ce9caa0bf035c8e9133fbf4ffa21.tar.bz2 |
Too many audio hangs Leopard
BUG=30242
TEST=Go to this page:
http://weston.ruter.net/projects/test-cases/chrome-mp3-audio-crash/
Click play and it won't hang.
Opening (not) too many audio streams in Leopard will cause a
deadlock in AudioQueue, freezing the browser process. Unfortunately
there isn't a way to detect that in the AudioQueue API. So this
change limits the number of streams allowed.
The limit for Leopard is set to 15 and other OSes are 50.
Review URL: http://codereview.chromium.org/1559024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44419 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/renderer_host')
-rw-r--r-- | chrome/browser/renderer_host/audio_renderer_host.cc | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/chrome/browser/renderer_host/audio_renderer_host.cc b/chrome/browser/renderer_host/audio_renderer_host.cc index 8d0a91c..10e9c77 100644 --- a/chrome/browser/renderer_host/audio_renderer_host.cc +++ b/chrome/browser/renderer_host/audio_renderer_host.cc @@ -26,6 +26,7 @@ #include "base/lock.h" #include "base/process.h" #include "base/shared_memory.h" +#include "base/sys_info.h" #include "base/waitable_event.h" #include "chrome/common/render_messages.h" #include "ipc/ipc_logging.h" @@ -34,22 +35,50 @@ namespace { // This constant governs the hardware audio buffer size, this value should be // choosen carefully and is platform specific. -const int kSamplesPerHardwarePacket = 8192; +static const int kSamplesPerHardwarePacket = 8192; // If the size of the buffer is less than this number, then the low latency // mode is to be used. -const uint32 kLowLatencyPacketThreshold = 1025; +static const uint32 kLowLatencyPacketThreshold = 1025; -const uint32 kMegabytes = 1024 * 1024; +static const uint32 kMegabytes = 1024 * 1024; // The following parameters limit the request buffer and packet size from the // renderer to avoid renderer from requesting too much memory. -const uint32 kMaxDecodedPacketSize = 2 * kMegabytes; -const uint32 kMaxBufferCapacity = 5 * kMegabytes; +static const uint32 kMaxDecodedPacketSize = 2 * kMegabytes; +static const uint32 kMaxBufferCapacity = 5 * kMegabytes; static const int kMaxChannels = 32; static const int kMaxBitsPerSample = 64; static const int kMaxSampleRate = 192000; +// We allow at most 50 concurrent audio streams in most case. This is a +// rather high limit that is practically hard to reach. +static const size_t kMaxStreams = 50; + +// By experiment the maximum number of audio streams allowed in Leopard +// is 18. But we put a slightly smaller number just to be safe. +static const size_t kMaxStreamsLeopard = 15; + +// Returns the number of audio streams allowed. This is a practical limit to +// prevent failure caused by too many audio streams opened. +size_t GetMaxAudioStreamsAllowed() { +#if defined(OS_MACOSX) + // We are hitting a bug in Leopard where too many audio streams will cause + // a deadlock in the AudioQueue API when starting the stream. Unfortunately + // there's no way to detect it within the AudioQueue API, so we put a + // special hard limit only for Leopard. + // See bug: http://crbug.com/30242 + int32 major, minor, bugfix; + base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix); + if (major < 10 || (major == 10 && minor <= 5)) + return kMaxStreamsLeopard; +#endif + + // In OS other than OSX Leopard, the number of audio streams allowed is a + // lot more so we return a separate number. + return kMaxStreams; +} + } // namespace //----------------------------------------------------------------------------- @@ -331,6 +360,13 @@ void AudioRendererHost::IPCAudioSource::NotifyPacketReady( DCHECK(!shared_socket_.get()); AutoLock auto_lock(lock_); + + // If we don't have an outstanding request, we should take the data. + if (!outstanding_request_) { + NOTREACHED() << "Received an audio packet while there was no such request"; + return; + } + outstanding_request_ = false; // If reported size is greater than capacity of the shared memory, we have // an error. @@ -468,6 +504,15 @@ void AudioRendererHost::OnCreateStream( DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); DCHECK(Lookup(msg.routing_id(), stream_id) == NULL); + // Limit the number of audio streams opened. This is to prevent using + // excessive resources for a large number of audio streams. More + // importantly it prevents instability on certain systems. + // See bug: http://crbug.com/30242 + if (sources_.size() >= GetMaxAudioStreamsAllowed()) { + SendErrorMessage(msg.routing_id(), stream_id); + return; + } + IPCAudioSource* source = IPCAudioSource::CreateIPCAudioSource( this, process_id_, @@ -487,8 +532,6 @@ void AudioRendererHost::OnCreateStream( sources_.insert( std::make_pair( SourceID(source->route_id(), source->stream_id()), source)); - } else { - SendErrorMessage(msg.routing_id(), stream_id); } } |