From: Seungbae Shin Date: Thu, 7 Dec 2017 11:28:15 +0000 (+0900) Subject: Fix memory leak after wav playback X-Git-Tag: accepted/tizen/unified/20171214.154153^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f03c4df9522015b87e01cdc89cf61994de7586f7;p=platform%2Fcore%2Fmultimedia%2Flibmm-sound.git Fix memory leak after wav playback 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 --- diff --git a/packaging/libmm-sound.spec b/packaging/libmm-sound.spec index b342d8b..f309577 100644 --- a/packaging/libmm-sound.spec +++ b/packaging/libmm-sound.spec @@ -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 diff --git a/server/mm_sound_mgr_codec.c b/server/mm_sound_mgr_codec.c index afb4760..babb2cd 100644 --- a/server/mm_sound_mgr_codec.c +++ b/server/mm_sound_mgr_codec.c @@ -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 diff --git a/server/plugin/wav/mm_sound_plugin_codec_wave.c b/server/plugin/wav/mm_sound_plugin_codec_wave.c index 0686128..438f6e6 100644 --- a/server/plugin/wav/mm_sound_plugin_codec_wave.c +++ b/server/plugin/wav/mm_sound_plugin_codec_wave.c @@ -34,6 +34,7 @@ #include #include +#include #include 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; }