Backed out 2 changesets (bug 1286041) for asan failures in cubeb_pulse.c
authorWes Kocher <wkocher@mozilla.com>
Fri, 05 Aug 2016 11:05:33 -0700
changeset 397522 8a63d6398481690023698a5790be5b185b846a14
parent 397521 5a915c1da4ebb8cb00fdc63c685bd0f8e9854044
child 397523 eb8ec8e246d618a25915f66a77e10d1f866c9c36
push id25332
push usermaglione.k@gmail.com
push dateSat, 06 Aug 2016 21:21:51 +0000
bugs1286041
milestone51.0a1
backs out72e5792fe990871f53f6ccf8cf0f211e25026e7f
14d4b1e011ad12af5ae231bddaa17c47da3ebb6a
Backed out 2 changesets (bug 1286041) for asan failures in cubeb_pulse.c Backed out changeset 72e5792fe990 (bug 1286041) Backed out changeset 14d4b1e011ad (bug 1286041)
dom/media/AudioStream.cpp
media/libcubeb/README_MOZILLA
media/libcubeb/src/cubeb-internal.h
media/libcubeb/src/cubeb.c
media/libcubeb/src/cubeb_pulse.c
--- a/dom/media/AudioStream.cpp
+++ b/dom/media/AudioStream.cpp
@@ -395,19 +395,16 @@ AudioStream::SetVolume(double aVolume)
   }
 }
 
 void
 AudioStream::Start()
 {
   MonitorAutoLock mon(mMonitor);
   MOZ_ASSERT(mState == INITIALIZED);
-  // Callback might start before the return of the invoke
-  // change state to avoid any assert break.
-  mState = STARTED;
   auto r = InvokeCubeb(cubeb_stream_start);
   mState = r == CUBEB_OK ? STARTED : ERRORED;
   LOG("started, state %s", mState == STARTED ? "STARTED" : "ERRORED");
 }
 
 void
 AudioStream::Pause()
 {
@@ -591,17 +588,23 @@ long
 AudioStream::DataCallback(void* aBuffer, long aFrames)
 {
   MonitorAutoLock mon(mMonitor);
   MOZ_ASSERT(mState != SHUTDOWN, "No data callback after shutdown");
 
   auto writer = AudioBufferWriter(
     reinterpret_cast<AudioDataValue*>(aBuffer), mOutChannels, aFrames);
 
-  MOZ_ASSERT(mState != INITIALIZED);
+  // FIXME: cubeb_pulse sometimes calls us before cubeb_stream_start() is called.
+  // We don't want to consume audio data until Start() is called by the client.
+  if (mState == INITIALIZED) {
+    NS_WARNING("data callback fires before cubeb_stream_start() is called");
+    mAudioClock.UpdateFrameHistory(0, aFrames);
+    return writer.WriteZeros(aFrames);
+  }
 
   // NOTE: wasapi (others?) can call us back *after* stop()/Shutdown() (mState == SHUTDOWN)
   // Bug 996162
 
   if (mAudioClock.GetInputRate() == mAudioClock.GetOutputRate()) {
     GetUnprocessed(writer);
   } else {
     GetTimeStretched(writer);
--- a/media/libcubeb/README_MOZILLA
+++ b/media/libcubeb/README_MOZILLA
@@ -1,8 +1,8 @@
 The source from this directory was copied from the cubeb 
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
 
-The git commit ID used was 50b92089d92ca9e5d1bc222849d199cc0686867b.
+The git commit ID used was e4074131e4d422bfe260d29ab0a49fc368406ef4.
--- a/media/libcubeb/src/cubeb-internal.h
+++ b/media/libcubeb/src/cubeb-internal.h
@@ -6,39 +6,16 @@
  */
 #if !defined(CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5)
 #define CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5
 
 #include "cubeb/cubeb.h"
 #include <stdio.h>
 #include <string.h>
 
-#ifdef __clang__
-#ifndef CLANG_ANALYZER_NORETURN
-#if __has_feature(attribute_analyzer_noreturn)
-#define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
-#else
-#define CLANG_ANALYZER_NORETURN
-#endif // ifndef CLANG_ANALYZER_NORETURN
-#endif // __has_feature(attribute_analyzer_noreturn)
-#else // __clang__
-#define CLANG_ANALYZER_NORETURN
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/* Crash the caller.  */
-void cubeb_crash() CLANG_ANALYZER_NORETURN;
-
-#if defined(__cplusplus)
-}
-#endif
-
 struct cubeb_ops {
   int (* init)(cubeb ** context, char const * context_name);
   char const * (* get_backend_id)(cubeb * context);
   int (* get_max_channel_count)(cubeb * context, uint32_t * max_channels);
   int (* get_min_latency)(cubeb * context,
                           cubeb_stream_params params,
                           uint32_t * latency_ms);
   int (* get_preferred_sample_rate)(cubeb * context, uint32_t * rate);
@@ -70,16 +47,17 @@ struct cubeb_ops {
   int (* stream_register_device_changed_callback)(cubeb_stream * stream,
                                                   cubeb_device_changed_callback device_changed_callback);
   int (* register_device_collection_changed)(cubeb * context,
                                              cubeb_device_type devtype,
                                              cubeb_device_collection_changed_callback callback,
                                              void * user_ptr);
 };
 
-#define XASSERT(expr) do {                                                     \
-    if (!(expr)) {                                                             \
+#define XASSERT(expr) do {                                              \
+    if (!(expr)) {                                                      \
       fprintf(stderr, "%s:%d - fatal error: %s\n", __FILE__, __LINE__, #expr); \
-      cubeb_crash();                                                           \
-    }                                                                          \
+      *((volatile int *) NULL) = 0;                                     \
+      abort();                                                          \
+    }                                                                   \
   } while (0)
 
 #endif /* CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5 */
--- a/media/libcubeb/src/cubeb.c
+++ b/media/libcubeb/src/cubeb.c
@@ -449,15 +449,8 @@ int cubeb_register_device_collection_cha
 
   if (!context->ops->register_device_collection_changed) {
     return CUBEB_ERROR_NOT_SUPPORTED;
   }
 
   return context->ops->register_device_collection_changed(context, devtype, callback, user_ptr);
 }
 
-void cubeb_crash()
-{
-  abort();
-  *((volatile int *) NULL) = 0;
-}
-
-
--- a/media/libcubeb/src/cubeb_pulse.c
+++ b/media/libcubeb/src/cubeb_pulse.c
@@ -68,24 +68,22 @@
   X(pa_threaded_mainloop_start)                 \
   X(pa_threaded_mainloop_stop)                  \
   X(pa_threaded_mainloop_unlock)                \
   X(pa_threaded_mainloop_wait)                  \
   X(pa_usec_to_bytes)                           \
   X(pa_stream_set_read_callback)                \
   X(pa_stream_connect_record)                   \
   X(pa_stream_readable_size)                    \
-  X(pa_stream_writable_size)                    \
   X(pa_stream_peek)                             \
   X(pa_stream_drop)                             \
   X(pa_stream_get_buffer_attr)                  \
   X(pa_stream_get_device_name)                  \
   X(pa_context_set_subscribe_callback)          \
   X(pa_context_subscribe)                       \
-  X(pa_mainloop_api_once)                       \
 
 #define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x;
 LIBPULSE_API_VISIT(MAKE_TYPEDEF);
 #undef MAKE_TYPEDEF
 #endif
 
 //#define LOGGING_ENABLED
 #ifdef LOGGING_ENABLED
@@ -117,17 +115,16 @@ struct cubeb_stream {
   cubeb_data_callback data_callback;
   cubeb_state_callback state_callback;
   void * user_ptr;
   pa_time_event * drain_timer;
   pa_sample_spec output_sample_spec;
   pa_sample_spec input_sample_spec;
   int shutdown;
   float volume;
-  cubeb_state state;
 };
 
 const float PULSE_NO_GAIN = -1.0;
 
 enum cork_state {
   UNCORK = 0,
   CORK = 1 << 0,
   NOTIFY = 1 << 1
@@ -171,38 +168,31 @@ context_notify_callback(pa_context * c, 
 static void
 stream_success_callback(pa_stream * s, int success, void * u)
 {
   cubeb_stream * stm = u;
   WRAP(pa_threaded_mainloop_signal)(stm->context->mainloop, 0);
 }
 
 static void
-stream_state_change_callback(cubeb_stream * stm, cubeb_state s)
-{
-  stm->state = s;
-  stm->state_callback(stm, stm->user_ptr, s);
-}
-
-static void
 stream_drain_callback(pa_mainloop_api * a, pa_time_event * e, struct timeval const * tv, void * u)
 {
   cubeb_stream * stm = u;
   /* there's no pa_rttime_free, so use this instead. */
   a->time_free(stm->drain_timer);
   stm->drain_timer = NULL;
-  stream_state_change_callback(stm, CUBEB_STATE_DRAINED);
+  stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
 }
 
 static void
 stream_state_callback(pa_stream * s, void * u)
 {
   cubeb_stream * stm = u;
   if (!PA_STREAM_IS_GOOD(WRAP(pa_stream_get_state)(s))) {
-    stream_state_change_callback(stm, CUBEB_STATE_ERROR);
+    stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
   }
   WRAP(pa_threaded_mainloop_signal)(stm->context->mainloop, 0);
 }
 
 static void
 trigger_user_callback(pa_stream * s, void const * input_data, size_t nbytes, cubeb_stream * stm)
 {
   void * buffer;
@@ -291,18 +281,17 @@ read_from_input(pa_stream * s, void cons
   return readable_size;
 }
 
 static void
 stream_write_callback(pa_stream * s, size_t nbytes, void * u)
 {
   LOG("Output callback to be written buffer size %zd\n", nbytes);
   cubeb_stream * stm = u;
-  if (stm->shutdown ||
-      stm->state != CUBEB_STATE_STARTED) {
+  if (stm->shutdown) {
     return;
   }
 
   if (!stm->input_stream){
     // Output/playback only operation.
     // Write directly to output
     assert(!stm->input_stream && stm->output_stream);
     trigger_user_callback(s, NULL, nbytes, stm);
@@ -430,18 +419,18 @@ static void
 stream_cork(cubeb_stream * stm, enum cork_state state)
 {
   WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
   cork_io_stream(stm, stm->output_stream, state);
   cork_io_stream(stm, stm->input_stream, state);
   WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
 
   if (state & NOTIFY) {
-    stream_state_change_callback(stm, state & CORK ? CUBEB_STATE_STOPPED
-                                                   : CUBEB_STATE_STARTED);
+    stm->state_callback(stm, stm->user_ptr,
+                        state & CORK ? CUBEB_STATE_STOPPED : CUBEB_STATE_STARTED);
   }
 }
 
 static int
 stream_update_timing_info(cubeb_stream * stm)
 {
   int r = -1;
   pa_operation * o = NULL;
@@ -725,17 +714,16 @@ pulse_stream_init(cubeb * context,
   stm = calloc(1, sizeof(*stm));
   assert(stm);
 
   stm->context = context;
   stm->data_callback = data_callback;
   stm->state_callback = state_callback;
   stm->user_ptr = user_ptr;
   stm->volume = PULSE_NO_GAIN;
-  stm->state = -1;
 
   WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
   if (output_stream_params) {
     r = create_pa_stream(stm, &stm->output_stream, output_stream_params, stream_name);
     if (r != CUBEB_OK) {
       WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
       pulse_stream_destroy(stm);
       return r;
@@ -837,39 +825,20 @@ pulse_stream_destroy(cubeb_stream * stm)
     WRAP(pa_stream_disconnect)(stm->input_stream);
     WRAP(pa_stream_unref)(stm->input_stream);
   }
   WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
 
   free(stm);
 }
 
-void
-pulse_defer_event_cb(pa_mainloop_api * a, void * userdata)
-{
-  cubeb_stream * stm = userdata;
-  size_t writable_size = WRAP(pa_stream_writable_size)(stm->output_stream);
-  trigger_user_callback(stm->output_stream, NULL, writable_size, stm);
-}
-
 static int
 pulse_stream_start(cubeb_stream * stm)
 {
   stream_cork(stm, UNCORK | NOTIFY);
-
-  if (stm->output_stream && !stm->input_stream) {
-    /* On output only case need to manually call user cb once in order to make
-     * things roll. This is done via a defer event in order to execute it
-     * from PA server thread. */
-    WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
-    WRAP(pa_mainloop_api_once)(WRAP(pa_threaded_mainloop_get_api)(stm->context->mainloop),
-                               pulse_defer_event_cb, stm);
-    WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
-  }
-
   return CUBEB_OK;
 }
 
 static int
 pulse_stream_stop(cubeb_stream * stm)
 {
   stream_cork(stm, CORK | NOTIFY);
   return CUBEB_OK;