diff options
author | Chris Hall <chris.hall@highwayman.com> | 2011-07-21 19:53:02 +0100 |
---|---|---|
committer | Chris Hall <chris.hall@highwayman.com> | 2011-07-21 19:53:02 +0100 |
commit | 56da2a1c9b6361e302b7a39fe2740561a9012d88 (patch) | |
tree | 6b6543532133a0c618d0f4ec70a87cf3f96caf30 /lib/pthread_safe.c | |
parent | e535bc959729262480a9702e71334002edee3f8c (diff) | |
download | quagga-56da2a1c9b6361e302b7a39fe2740561a9012d88.tar.bz2 quagga-56da2a1c9b6361e302b7a39fe2740561a9012d88.tar.xz |
Update pipework and improve memory reporting.
Improve error handling for all new pipework inputs and outputs.
Change behaviour of ^C from VTY Terminal, so that will interrupt
output and terminate all running pipes -- including running
shell commands.
In pipe commands, recognise "~/..." and "~user/..." home directory
forms.
Changed "~/" to mean the usual home for the current user. "~~/"
now means the configuration file directory.
Introduced "shdir DIR" command to show what is (currently) what.
Changed "<|" so that if the command has a path, it is expanded
using Quagga's rules (including "~~/" and "~./") and the
"here" directory is set to that path.
Fixed collection of stderr output from all pipes so that is
separate from stdout output, and is always sent to the base
output (eg VTY Terminal).
Increase amount of information about the heap that "show mem"
shows -- particularly if the "memory_tracker" is enabled.
Tested and applied resulting fixes.
Diffstat (limited to 'lib/pthread_safe.c')
-rw-r--r-- | lib/pthread_safe.c | 160 |
1 files changed, 115 insertions, 45 deletions
diff --git a/lib/pthread_safe.c b/lib/pthread_safe.c index 4a698216..336f686e 100644 --- a/lib/pthread_safe.c +++ b/lib/pthread_safe.c @@ -47,16 +47,25 @@ #include "qfstring.h" #include "errno_names.h" -/* prototypes */ -static void destructor(void* data); -static char * thread_buff(void); - +/*============================================================================== + * Initialisation, close down and local variables. + * + * Note that the "thread_safe" mutex is recursive, so one thread safe function + * can call another, if required. + */ static pthread_key_t tsd_key; static const int buff_size = 1024; +static qpt_mutex thread_safe = NULL ; + static const char ellipsis[] = "..." ; -/* Module initialization, before any threads have been created */ +static void destructor(void* data); +static char * thread_buff(void); + +/*------------------------------------------------------------------------------ + * Module initialization, before any threads have been created + */ void safe_init_r(void) { @@ -66,50 +75,36 @@ safe_init_r(void) status = pthread_key_create(&tsd_key, destructor); if (status != 0) zabort("Can't create thread specific data key"); - } + + qassert(thread_safe == NULL) ; + + thread_safe = qpt_mutex_init_new(NULL, qpt_mutex_recursive) ; + } ; } -/* Clean up */ +/*------------------------------------------------------------------------------ + * Clean up + */ void safe_finish(void) { if (qpthreads_enabled) - pthread_key_delete(tsd_key); -} + { + pthread_key_delete(tsd_key) ; -/* called when thread terminates, clean up */ + thread_safe = qpt_mutex_destroy(thread_safe, free_it) ; + } ; +} ; + +/*------------------------------------------------------------------------------ + * called when thread terminates, clean up + */ static void destructor(void* data) { XFREE(MTYPE_TSD, data); } -/* Thread safe version of strerror. Never returns NULL. - * Contents of result remains intact until another call of - * a safe_ function. - */ -const char * -safe_strerror(int errnum) -{ - static const char * unknown = "Unknown error"; - if (qpthreads_enabled) - { - char * buff = thread_buff(); - int ret = strerror_r(errnum, buff, buff_size); - - return (ret >= 0) - ? buff - : unknown; - } - else - { - const char *s = strerror(errnum); - return (s != NULL) - ? s - : unknown; - } -} - /*============================================================================== * Alternative error number handling. * @@ -311,14 +306,14 @@ errtox(strerror_t* st, int err, uint len, uint want) if (ql != 0) qfs_append(qfs, q) ; - - /* '\0' terminate -- if has overflowed, replace last few characters - * by "..." -- noting that sizeof("...") includes the '\0'. - */ - if (qfs_term(qfs) != 0) - qfs_term_string(qfs, ellipsis, sizeof(ellipsis)) ; } ; + /* '\0' terminate -- if has overflowed, replace last few characters + * by "..." -- noting that sizeof("...") includes the '\0'. + */ + if (qfs_term(qfs) != 0) + qfs_term_string(qfs, ellipsis, sizeof(ellipsis)) ; + /* Put back errno */ errno = errno_saved ; } ; @@ -490,9 +485,83 @@ eaitox(strerror_t* st, int eai, int err, uint len, uint want) errno = errno_saved ; } ; -/*============================================================================*/ +/*============================================================================== + * Miscellaneous thread-safe functions + */ + +/*------------------------------------------------------------------------------ + * getenv_r -- fetch environment variable into the given buffer. + * + * If buffer is not long enough, fetches as much as can and '\0' terminates. + * + * Returns: -1 => not found -- buffer set empty + * >= 0 == length of environment variable + * + * NB: this is NOT signal safe. If need value of environment variable in + * a signal action -- make OTHER arrangements !! + */ +extern int +getenv_r(const char* name, char* buf, int buf_len) +{ + char* val ; + int len ; + int cl ; + + qpt_mutex_lock(thread_safe) ; -/* Thread safe version of inet_ntoa. Never returns NULL. + val = getenv(name) ; + if (val == NULL) + { + len = -1 ; + cl = 0 ; + } + else + { + len = strlen(val) ; + cl = (len < buf_len) ? len : buf_len - 1 ; + } ; + + if (buf_len > 0) + { + if (cl > 0) + memcpy(buf, val, cl) ; + buf[cl] = '\0' ; + } ; + + qpt_mutex_unlock(thread_safe) ; + + return len ; +} ; + +/*------------------------------------------------------------------------------ + * Thread safe version of strerror. Never returns NULL. + * Contents of result remains intact until another call of + * a safe_ function. + */ +const char * +safe_strerror(int errnum) +{ + static const char * unknown = "Unknown error"; + if (qpthreads_enabled) + { + char * buff = thread_buff(); + int ret = strerror_r(errnum, buff, buff_size); + + return (ret >= 0) + ? buff + : unknown; + } + else + { + const char *s = strerror(errnum); + return (s != NULL) + ? s + : unknown; + } +} + +/*------------------------------------------------------------------------------ + * Thread safe version of inet_ntoa. Never returns NULL. * Contents of result remains intact until another call of * a safe_ function. */ @@ -511,7 +580,8 @@ safe_inet_ntoa (struct in_addr in) : unknown; } -/* Return the thread's buffer, create it if necessary. +/*------------------------------------------------------------------------------ + * Return the thread's buffer, create it if necessary. * (pthread Thread Specific Data) */ static char * |