diff options
-rw-r--r-- | api/src/glfs.c | 60 | ||||
-rw-r--r-- | libglusterfs/src/globals.c | 7 | ||||
-rw-r--r-- | libglusterfs/src/logging.c | 4 | ||||
-rw-r--r-- | libglusterfs/src/logging.h | 2 | ||||
-rw-r--r-- | libglusterfs/src/unittest/log_mock.c | 2 | ||||
-rwxr-xr-x | tests/bugs/libgfapi/bug-1319374-THIS-crash.sh | 27 | ||||
-rw-r--r-- | tests/bugs/libgfapi/bug-1319374.c | 128 |
7 files changed, 218 insertions, 12 deletions
diff --git a/api/src/glfs.c b/api/src/glfs.c index 037b579225f..6c152ae56ed 100644 --- a/api/src/glfs.c +++ b/api/src/glfs.c @@ -651,6 +651,49 @@ err: return NULL; } +extern xlator_t global_xlator; +extern glusterfs_ctx_t *global_ctx; +extern pthread_mutex_t global_ctx_mutex; + +static int +glfs_init_global_ctx () +{ + int ret = 0; + glusterfs_ctx_t *ctx = NULL; + + pthread_mutex_lock (&global_ctx_mutex); + { + if (global_xlator.ctx) + goto unlock; + + ctx = glusterfs_ctx_new (); + if (!ctx) { + ret = -1; + goto unlock; + } + + gf_log_globals_init (ctx, GF_LOG_NONE); + + global_ctx = ctx; + global_xlator.ctx = global_ctx; + + ret = glusterfs_ctx_defaults_init (ctx); + if (ret) { + global_ctx = NULL; + global_xlator.ctx = NULL; + goto unlock; + } + } +unlock: + pthread_mutex_unlock (&global_ctx_mutex); + + if (ret) + FREE (ctx); + + return ret; +} + + struct glfs * pub_glfs_new (const char *volname) { @@ -679,11 +722,9 @@ pub_glfs_new (const char *volname) goto fini; old_THIS = THIS; - /* THIS is set to NULL so that we do not modify the caller xlators' - * ctx, instead we set the global_xlator->ctx - */ - THIS = NULL; - THIS->ctx = ctx; + ret = glfs_init_global_ctx (); + if (ret) + goto fini; /* then ctx_defaults_init, for xlator_mem_acct_init(THIS) */ @@ -795,12 +836,16 @@ GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_volfile, 3.4.0); int pub_glfs_set_logging (struct glfs *fs, const char *logfile, int loglevel) { - int ret = -1; - char *tmplog = NULL; + int ret = -1; + char *tmplog = NULL; + glusterfs_ctx_t *old_ctx = NULL; DECLARE_OLD_THIS; __GLFS_ENTRY_VALIDATE_FS (fs, invalid_fs); + old_ctx = THIS->ctx; + THIS->ctx = fs->ctx; + if (!logfile) { ret = gf_set_log_file_path (&fs->ctx->cmd_args); if (ret) @@ -823,6 +868,7 @@ pub_glfs_set_logging (struct glfs *fs, const char *logfile, int loglevel) goto out; out: + THIS->ctx = old_ctx; __GLFS_EXIT_FS; invalid_fs: diff --git a/libglusterfs/src/globals.c b/libglusterfs/src/globals.c index 3cc29c5491c..435921d64cc 100644 --- a/libglusterfs/src/globals.c +++ b/libglusterfs/src/globals.c @@ -72,6 +72,11 @@ const char *gf_fop_list[GF_FOP_MAXVALUE] = { }; /* THIS */ +/* This global ctx is a bad hack to prevent some of the libgfapi crashes. + * This should be removed once the patch on resource pool is accepted + */ +glusterfs_ctx_t *global_ctx = NULL; +pthread_mutex_t global_ctx_mutex = PTHREAD_MUTEX_INITIALIZER; xlator_t global_xlator; static pthread_key_t this_xlator_key; static pthread_key_t synctask_key; @@ -383,7 +388,7 @@ glusterfs_globals_init (glusterfs_ctx_t *ctx) { int ret = 0; - gf_log_globals_init (ctx); + gf_log_globals_init (ctx, GF_LOG_INFO); ret = pthread_once (&globals_inited, gf_globals_init_once); diff --git a/libglusterfs/src/logging.c b/libglusterfs/src/logging.c index 1d7ac4c785b..62f19b9d3e3 100644 --- a/libglusterfs/src/logging.c +++ b/libglusterfs/src/logging.c @@ -642,13 +642,13 @@ gf_syslog (int facility_priority, char *format, ...) } void -gf_log_globals_init (void *data) +gf_log_globals_init (void *data, gf_loglevel_t level) { glusterfs_ctx_t *ctx = data; pthread_mutex_init (&ctx->log.logfile_mutex, NULL); - ctx->log.loglevel = GF_LOG_INFO; + ctx->log.loglevel = level; ctx->log.gf_log_syslog = 1; ctx->log.sys_log_level = GF_LOG_CRITICAL; ctx->log.logger = gf_logger_glusterlog; diff --git a/libglusterfs/src/logging.h b/libglusterfs/src/logging.h index 25a9e42d71c..3c7346f8cc7 100644 --- a/libglusterfs/src/logging.h +++ b/libglusterfs/src/logging.h @@ -134,7 +134,7 @@ typedef struct log_buf_ { struct list_head msg_list; } log_buf_t; -void gf_log_globals_init (void *ctx); +void gf_log_globals_init (void *ctx, gf_loglevel_t level); int gf_log_init (void *data, const char *filename, const char *ident); void gf_log_logrotate (int signum); diff --git a/libglusterfs/src/unittest/log_mock.c b/libglusterfs/src/unittest/log_mock.c index b35e03b3618..c03ff524612 100644 --- a/libglusterfs/src/unittest/log_mock.c +++ b/libglusterfs/src/unittest/log_mock.c @@ -47,4 +47,4 @@ int _gf_msg_nomem (const char *domain, const char *file, } void -gf_log_globals_init (void *data) {} +gf_log_globals_init (void *data, gf_loglevel_t level) {} diff --git a/tests/bugs/libgfapi/bug-1319374-THIS-crash.sh b/tests/bugs/libgfapi/bug-1319374-THIS-crash.sh new file mode 100755 index 00000000000..9aea739377b --- /dev/null +++ b/tests/bugs/libgfapi/bug-1319374-THIS-crash.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +TEST $CLI volume create $V0 $H0:$B0/brick1 $H0:$B0/brick2; +EXPECT 'Created' volinfo_field $V0 'Status'; + +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +TEST $CLI volume set $V0 diagnostics.client-log-flush-timeout 30 + +logdir=`gluster --print-logdir` + +build_tester $(dirname $0)/bug-1319374.c -lgfapi +TEST $(dirname $0)/bug-1319374 $V0 $logdir/bug-1319374.log + +cleanup_tester $(dirname $0)/bug-1319374 + +cleanup; diff --git a/tests/bugs/libgfapi/bug-1319374.c b/tests/bugs/libgfapi/bug-1319374.c new file mode 100644 index 00000000000..878d897dde6 --- /dev/null +++ b/tests/bugs/libgfapi/bug-1319374.c @@ -0,0 +1,128 @@ +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#define NO_INIT 1 + +glfs_t * +setup_new_client(char *volname, char *log_file, int flag) +{ + int ret = 0; + glfs_t *fs = NULL; + + fs = glfs_new (volname); + if (!fs) { + fprintf (stderr, "\nglfs_new: returned NULL (%s)\n", + strerror (errno)); + goto error; + } + + ret = glfs_set_volfile_server (fs, "tcp", "localhost", 24007); + if (ret < 0) { + fprintf (stderr, "\nglfs_set_volfile_server failed ret:%d (%s)\n", + ret, strerror (errno)); + goto error; + } + + ret = glfs_set_logging (fs, log_file, 7); + if (ret < 0) { + fprintf (stderr, "\nglfs_set_logging failed with ret: %d (%s)\n", + ret, strerror (errno)); + goto error; + } + + if (flag == NO_INIT) + goto out; + + ret = glfs_init (fs); + if (ret < 0) { + fprintf (stderr, "\nglfs_init failed with ret: %d (%s)\n", + ret, strerror (errno)); + goto error; + } + +out: + return fs; +error: + return NULL; +} + +int +main (int argc, char *argv[]) +{ + int ret = 0; + glfs_t *fs1 = NULL; + glfs_t *fs2 = NULL; + glfs_t *fs3 = NULL; + char *volname = NULL; + char *log_file = NULL; + + if (argc != 3) { + fprintf (stderr, + "Expect following args %s <Vol> <log file location>\n" + , argv[0]); + return -1; + } + + volname = argv[1]; + log_file = argv[2]; + + fs1 = setup_new_client (volname, log_file, NO_INIT); + if (!fs1) { + fprintf (stderr, "\nsetup_new_client: returned NULL (%s)\n", + strerror (errno)); + goto error; + } + + fs2 = setup_new_client (volname, log_file, 0); + if (!fs2) { + fprintf (stderr, "\nsetup_new_client: returned NULL (%s)\n", + strerror (errno)); + goto error; + } + + fs3 = setup_new_client (volname, log_file, 0); + if (!fs3) { + fprintf (stderr, "\nsetup_new_client: returned NULL (%s)\n", + strerror (errno)); + goto error; + } + + ret = glfs_fini (fs3); + if (ret < 0) { + fprintf (stderr, "glfs_fini failed with ret: %d (%s)\n", + ret, strerror (errno)); + goto error; + } + + /* The crash is seen in gf_log_flush_timeout_cbk(), and this gets + * triggered when 30s timer expires, hence the sleep of 31s + */ + sleep (31); + ret = glfs_fini (fs2); + if (ret < 0) { + fprintf (stderr, "glfs_fini failed with ret: %d (%s)\n", + ret, strerror (errno)); + goto error; + } + + ret = glfs_init (fs1); + if (ret < 0) { + fprintf (stderr, "\nglfs_init failed with ret: %d (%s)\n", + ret, strerror (errno)); + goto error; + } + + ret = glfs_fini (fs1); + if (ret < 0) { + fprintf (stderr, "glfs_fini failed with ret: %d (%s)\n", + ret, strerror (errno)); + goto error; + } + + return 0; +error: + return -1; +} |