diff options
-rw-r--r-- | tests/bugs/bug-1110917.t | 39 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog-helpers.c | 34 |
2 files changed, 73 insertions, 0 deletions
diff --git a/tests/bugs/bug-1110917.t b/tests/bugs/bug-1110917.t new file mode 100644 index 00000000000..927b2342192 --- /dev/null +++ b/tests/bugs/bug-1110917.t @@ -0,0 +1,39 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/brick1 $H0:$B0/brick2; +TEST $CLI volume start $V0; + +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 + +TEST $CLI volume set $V0 changelog on +TEST $CLI volume set $V0 changelog.fsync-interval 1 + +# perform I/O on the background +f=$(basename `mktemp`) +dd if=/dev/urandom of=$M0/$f count=100000 bs=4k & + +# this is the best we can do without inducing _error points_ in the code +# without the patch reconfigre() would hang... +TEST $CLI volume set $V0 changelog.rollover-time `expr $((RANDOM % 9)) + 1` +TEST $CLI volume set $V0 changelog.rollover-time `expr $((RANDOM % 9)) + 1` + +TEST $CLI volume set $V0 changelog off +TEST $CLI volume set $V0 changelog on +TEST $CLI volume set $V0 changelog off +TEST $CLI volume set $V0 changelog on + +TEST $CLI volume set $V0 changelog.rollover-time `expr $((RANDOM % 9)) + 1` +TEST $CLI volume set $V0 changelog.rollover-time `expr $((RANDOM % 9)) + 1` + +# if there's a deadlock, this would hang +wait; + +cleanup; diff --git a/xlators/features/changelog/src/changelog-helpers.c b/xlators/features/changelog/src/changelog-helpers.c index b271f3f0fc0..bb8150bd719 100644 --- a/xlators/features/changelog/src/changelog-helpers.c +++ b/xlators/features/changelog/src/changelog-helpers.c @@ -25,6 +25,28 @@ #include "changelog-encoders.h" #include <pthread.h> +inline void +__mask_cancellation (xlator_t *this) +{ + int ret = 0; + + ret = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); + if (ret) + gf_log (this->name, GF_LOG_WARNING, + "failed to disable thread cancellation"); +} + +inline void +__unmask_cancellation (xlator_t *this) +{ + int ret = 0; + + ret = pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + if (ret) + gf_log (this->name, GF_LOG_WARNING, + "failed to enable thread cancellation"); +} + static void changelog_cleanup_free_mutex (void *arg_mutex) { @@ -618,6 +640,8 @@ changelog_rollover (void *data) slice = &priv->slice; while (1) { + (void) pthread_testcancel(); + tv.tv_sec = priv->rollover_time; tv.tv_usec = 0; FD_ZERO(&rset); @@ -708,6 +732,8 @@ changelog_rollover (void *data) continue; } + __mask_cancellation (this); + LOCK (&priv->lock); { ret = changelog_inject_single_event (this, priv, &cld); @@ -715,6 +741,8 @@ changelog_rollover (void *data) SLICE_VERSION_UPDATE (slice); } UNLOCK (&priv->lock); + + __unmask_cancellation (this); } return NULL; @@ -733,6 +761,8 @@ changelog_fsync_thread (void *data) cld.cld_type = CHANGELOG_TYPE_FSYNC; while (1) { + (void) pthread_testcancel(); + tv.tv_sec = priv->fsync_interval; tv.tv_usec = 0; @@ -740,10 +770,14 @@ changelog_fsync_thread (void *data) if (ret) continue; + __mask_cancellation (this); + ret = changelog_inject_single_event (this, priv, &cld); if (ret) gf_log (this->name, GF_LOG_ERROR, "failed to inject fsync event"); + + __unmask_cancellation (this); } return NULL; |