Free all possibly held mutexes in error handlers

Now that we have 3 mutexes lying around, it's important that we check
and free these if necessary if error() is called in any thread that can
hold them.  To do this, we now have flexthread.c, which defines a
flexthread_mutex struct.  This is a wrapper around a pthread_mutex_t and
a pthread_t.  The idea is that in the error handler, the thread can
check whether it holds the mutex and can free it if and only if it does.
This is important because pthread fast mutexes can be freed by *any*
thread, not just the thread which holds them.

Note: it is only ever safe for a thread to check if it holds the mutex
itself.  It is *never* safe to check if another thread holds a mutex
without first locking that mutex, which makes the whole operation rather
pointless.
This commit is contained in:
Alex Young
2012-07-11 09:43:16 +01:00
parent 17fe6d3023
commit f3f017a87d
17 changed files with 351 additions and 70 deletions

View File

@@ -23,7 +23,6 @@
#include "readwrite.h"
#include "bitset.h"
#include "self_pipe.h"
#include "acl.h"
#include "status.h"
@@ -182,6 +181,7 @@ int mirror_pass(struct server * serve, int should_lock, uint64_t *written)
*/
if (should_lock) { server_lock_io( serve ); }
{
debug("in lock block");
/** FIXME: do something useful with bytes/second */
/** FIXME: error handling code here won't unlock */
@@ -194,6 +194,7 @@ int mirror_pass(struct server * serve, int should_lock, uint64_t *written)
/* now mark it clean */
bitset_clear_range(map, current, run);
debug("leaving lock block");
}
if (should_lock) { server_unlock_io( serve ); }
@@ -280,9 +281,11 @@ void mirror_on_exit( struct server * serve )
}
void mirror_cleanup( struct mirror_status * mirror,
void mirror_cleanup( struct server * serve,
int fatal __attribute__((unused)))
{
NULLCHECK( serve );
struct mirror_status * mirror = serve->mirror;
NULLCHECK( mirror );
info( "Cleaning up mirror thread");
@@ -290,6 +293,8 @@ void mirror_cleanup( struct mirror_status * mirror,
close( mirror->client );
}
mirror->client = -1;
if( server_io_locked( serve ) ){ server_unlock_io( serve ); }
}
@@ -404,7 +409,7 @@ void* mirror_runner(void* serve_params_uncast)
struct mirror_status * mirror = serve->mirror;
NULLCHECK( mirror->dirty_map );
error_set_handler( (cleanup_handler *) mirror_cleanup, mirror );
error_set_handler( (cleanup_handler *) mirror_cleanup, serve );
info( "Connecting to mirror" );