From 6d6fcaba2c7b55b9817ec0ee8b0dc9239ea3895d Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Denis-Courmont?= Date: Wed, 6 Jan 2010 14:20:33 +0200 Subject: [PATCH] vlc_tdestroy: safe replacement for GNU tdestroy() --- configure.ac | 2 +- include/vlc_common.h | 2 + include/vlc_fixups.h | 4 ++ src/Makefile.am | 1 + src/extras/tdestroy.c | 117 ++++++++++++++++++++++++++++++++++++++++++ src/libvlccore.sym | 1 + 6 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/extras/tdestroy.c diff --git a/configure.ac b/configure.ac index 4a1bc8ccd0..526bf4db49 100644 --- a/configure.ac +++ b/configure.ac @@ -568,7 +568,7 @@ dnl Check for system libs needed need_libc=false dnl Check for usual libc functions -AC_CHECK_FUNCS([gettimeofday isatty getpwuid_r memalign posix_memalign getenv putenv setenv ctime_r daemon fork lstat posix_fadvise posix_madvise uselocale]) +AC_CHECK_FUNCS([gettimeofday isatty getpwuid_r memalign posix_memalign getenv putenv setenv ctime_r daemon fork lstat posix_fadvise posix_madvise uselocale tdestroy]) AC_CHECK_FUNCS(fcntl) AC_REPLACE_FUNCS([asprintf atof atoll getcwd getpid gmtime_r lldiv localtime_r rewind strcasecmp strcasestr strdup strlcpy strncasecmp strndup strnlen strsep strtof strtok_r strtoll vasprintf swab]) AC_CHECK_FUNCS([stricmp strnicmp]) diff --git a/include/vlc_common.h b/include/vlc_common.h index d817166d61..b2b3b4af2b 100644 --- a/include/vlc_common.h +++ b/include/vlc_common.h @@ -818,6 +818,8 @@ VLC_EXPORT( int, __vlc_execve, ( vlc_object_t *p_object, int i_argc, char *const /* dir wrappers (defined in src/extras/libc.c) */ VLC_EXPORT(int, vlc_wclosedir, ( void *_p_dir )); +VLC_EXPORT( void, vlc_tdestroy, ( void *, void (*)(void *) ) ); + /* Fast large memory copy and memory set */ VLC_EXPORT( void *, vlc_memcpy, ( void *, const void *, size_t ) ); VLC_EXPORT( void *, vlc_memset, ( void *, int, size_t ) ); diff --git a/include/vlc_fixups.h b/include/vlc_fixups.h index 7f85f6ea2e..e1680ae69f 100644 --- a/include/vlc_fixups.h +++ b/include/vlc_fixups.h @@ -234,4 +234,8 @@ struct pollfd # define poll(a, b, c) vlc_poll(a, b, c) #endif +#ifndef HAVE_TDESTROY +# define tdestroy vlc_tdestroy +#endif + #endif /* !LIBVLC_FIXUPS_H */ diff --git a/src/Makefile.am b/src/Makefile.am index 2f81f6f9ee..c20f17a990 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -441,6 +441,7 @@ SOURCES_libvlc_common = \ misc/update_crypto.c \ misc/xml.c \ extras/libc.c \ + extras/tdestroy.c \ misc/filter.c \ misc/filter_chain.c \ misc/http_auth.c \ diff --git a/src/extras/tdestroy.c b/src/extras/tdestroy.c new file mode 100644 index 0000000000..aeb43bbafc --- /dev/null +++ b/src/extras/tdestroy.c @@ -0,0 +1,117 @@ +/** + * @file tdestroy.c + * @brief replacement for GNU tdestroy() + */ +/***************************************************************************** + * Copyright (C) 2009 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include + +#ifdef HAVE_TDESTROY +void vlc_tdestroy (void *root, void (*freenode) (void *)) +{ + (void) root; + assert (freenode != NULL); + abort (); +} + +#else +#include + +static struct +{ + const void **tab; + size_t count; + vlc_mutex_t lock; +} list = { NULL, 0, VLC_STATIC_MUTEX }; + +static void list_nodes (const void *node, const VISIT which, const int depth) +{ + (void) depth; + + if (which != postorder && which != leaf) + return; + + const void **tab = realloc (list.tab, sizeof (*tab) * (list.count + 1)); + if (unlikely(tab == NULL)) + abort (); + + tab[list.count] = *(const void **)node; + list.tab = tab; + list.count++; +} + +static struct +{ + const void *node; + vlc_mutex_t lock; +} smallest = { NULL, VLC_STATIC_MUTEX }; + +static int cmp_smallest (const void *a, const void *b) +{ + if (a == b) + return 0; + if (a == smallest.node) + return -1; + if (likely(b == smallest.node)) + return +1; + abort (); +} + +void vlc_tdestroy (void *root, void (*freenode) (void *)) +{ + const void **tab; + size_t count; + + assert (freenode != NULL); + + /* Enumerate nodes in order */ + vlc_mutex_lock (&list.lock); + assert (list.count == 0); + twalk (root, list_nodes); + tab = list.tab; + count = list.count; + list.tab = NULL; + list.count = 0; + vlc_mutex_unlock (&list.lock); + + /* Destroy the tree */ + vlc_mutex_lock (&smallest.lock); + for (size_t i = 0; i < count; i++) + { + smallest.node = tab[i]; + if (tdelete (smallest.node, &root, cmp_smallest) == NULL) + abort (); + } + vlc_mutex_unlock (&smallest.lock); + assert (root == NULL); + + /* Destroy the nodes */ + for (size_t i = 0; i < count; i++) + freenode ((void *)(tab[i])); + free (tab); +} + +#endif diff --git a/src/libvlccore.sym b/src/libvlccore.sym index 9217093364..9bbf800998 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -528,6 +528,7 @@ __vlc_object_set_destructor vlc_object_get_name vlc_plugin_set vlc_poll +vlc_tdestroy vlc_rand_bytes vlc_release vlc_restorecancel -- 2.39.2