Fix memory leak after wav playback 45/163545/1 accepted/tizen/unified/20171214.154153 submit/tizen/20171214.052526
authorSeungbae Shin <seungbae.shin@samsung.com>
Thu, 7 Dec 2017 11:28:15 +0000 (20:28 +0900)
committerSeungbae Shin <seungbae.shin@samsung.com>
Tue, 12 Dec 2017 03:05:57 +0000 (12:05 +0900)
threaded_mainloop was not removed after wav playback,
now it will be removed on seperate temporal thread
(we can't remove from inside of mainloop thread)

in addition, change shutdown timeout from 10 to 60 sec.
(I think 10 sec. might be too short)

[Version] 0.12.5
[Issue Type] Bug Fix

Change-Id: Ic3a0053812fc3f31c344b9170a0684c656a97648

packaging/libmm-sound.spec
server/mm_sound_mgr_codec.c
server/plugin/wav/mm_sound_plugin_codec_wave.c

index b342d8b00cc4300747b4aff4e99c8b7950f2d844..f30957765fed97ebbc5c2c08f86bf9003300b1f8 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-sound
 Summary:    MMSound Package contains client lib and sound_server binary
-Version:    0.12.4
+Version:    0.12.5
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index afb4760e6965487cc6b3a1e4bb5fde1ba32e013d..babb2cd7fa303b139bb74eab6bdec2f54dfc844d 100644 (file)
@@ -42,7 +42,7 @@
 #include "../include/mm_sound_focus.h"
 #include "../include/mm_sound.h"
 
-#define SHUTDOWN_TIMEOUT_SEC 10
+#define SHUTDOWN_TIMEOUT_SEC 60
 #define STATUS_IDLE 0
 #define STATUS_SOUND 3
 #define SOUND_SLOT_START 0
index 06861286779ca867ae91ba7a98c684ef65720549..438f6e6ed33e38f68b6b4946f3ac20aac4fdb66c 100644 (file)
@@ -34,6 +34,7 @@
 #include <unistd.h>
 
 #include <sndfile.h>
+#include <pthread.h>
 #include <pulse/pulseaudio.h>
 
 typedef struct {
@@ -116,9 +117,60 @@ static void _pa_context_state_callback(pa_context *c, void *userdata)
        }
 }
 
+static void *_cleanup_thread_func(void *userdata)
+{
+       pa_threaded_mainloop *m = (pa_threaded_mainloop *)userdata;
+
+       if (m) {
+               debug_error("now stop and free threaded_mainloop(%p) here", m);
+               pa_threaded_mainloop_stop(m);
+               pa_threaded_mainloop_free(m);
+       } else {
+               debug_warning("thread mainloop is already null");
+       }
+
+       pthread_exit(NULL);
+}
+
+static void _cleanup_threaded_mainloop(pa_threaded_mainloop *m)
+{
+       int ret = 0;
+       pthread_t thread_id;
+       pthread_attr_t attr;
+
+       ret = pthread_attr_init(&attr);
+       if (ret != 0) {
+               debug_error("failed to init pthread attr!!! errno=%d", ret);
+               return;
+       }
+
+       ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+       if (ret != 0) {
+               debug_error("failed to set detach state!!! errno=%d", ret);
+               goto finish;
+       }
+
+       ret = pthread_create(&thread_id, &attr, _cleanup_thread_func, m);
+       if (ret != 0)
+               debug_error("failed to create _cleanup_thread_func!!! errno=%d", ret);
+
+finish:
+       ret = pthread_attr_destroy(&attr);
+       if (ret != 0)
+               debug_error("failed to destroy pthread attr!!! errno=%d", ret);
+
+       return;
+}
+
+
 static void _pa_context_drain_complete_callback(pa_context *c, void *userdata)
 {
+       debug_msg("context drain completed, cleanup context and mainloop");
+
        pa_context_disconnect(c);
+       pa_context_unref(c);
+
+       _cleanup_threaded_mainloop((pa_threaded_mainloop *)userdata);
 }
 
 /* Stream Callbacks */
@@ -159,10 +211,14 @@ static void _pa_stream_drain_complete_callback(pa_stream* s, int success, void *
        pa_stream_unref(h->s);
        h->s = NULL;
 
-       if (!(o = pa_context_drain(h->c, _pa_context_drain_complete_callback, h)))
+       if (!(o = pa_context_drain(h->c, _pa_context_drain_complete_callback, h->m))) {
+               debug_error("failed to drain context!");
                pa_context_disconnect(h->c);
-       else
+               pa_context_unref(h->c);
+               h->c = NULL;
+       } else {
                pa_operation_unref(o);
+       }
 
        debug_msg("Call stop callback(%p, %d) of mgr_codec", h->stop_cb, h->cb_param);
        if (h->stop_cb)
@@ -249,6 +305,8 @@ static void _pa_stream_write_callback(pa_stream *s, size_t length, void *userdat
                o = pa_stream_drain(s, _pa_stream_drain_complete_callback, h);
                if (o)
                        pa_operation_unref(o);
+               else
+                       debug_error("failed to drain stream %p", s);
        }
 }
 
@@ -406,6 +464,7 @@ static int _pa_stream_stop_disconnect(wave_info_t *h)
                h->s = NULL;
        }
        if (h->c) {
+               pa_context_disconnect(h->c);
                pa_context_unref(h->c);
                h->c = NULL;
        }