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 b342d8b..f309577 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 afb4760..babb2cd 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 0686128..438f6e6 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;
        }