diff --git a/CMakeLists.txt b/CMakeLists.txt index 97593e3d5aad3efc9dc94337e4aca559ecf252b3..1b30a7c68eb2272bce83f87a6b92961ee74147d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 2.6) project(tarantool) include(CheckLibraryExists) include(CheckIncludeFile) +include(CheckCCompilerFlag) find_program(ECHO echo) find_program(CAT cat) find_program(GIT git) @@ -43,6 +44,12 @@ else() message (FATAL_ERROR "Unsupported platform -- ${CMAKE_SYSTEM_NAME}") endif() +# +# Some versions of GNU libc define non-portable __libc_stack_end +# which we use to determine the end (or beginning, actually) of +# stack. Find whether or not it's present. +check_library_exists("" __libc_stack_end "" HAVE_LIBC_STACK_END) + # # Tarantool uses 'coro' (coroutines) library # to implement # cooperative multi-tasking. Since coro.h is included @@ -140,6 +147,7 @@ with gcc. If GNU binutils and binutils-dev libraries are installed, backtrace is output with resolved function (symbol) names. Otherwise only frame addresses are printed." ${CMAKE_COMPILER_IS_GNUCC}) +set (HAVE_BFD False) if (ENABLE_BACKTRACE) if (NOT ${CMAKE_COMPILER_IS_GNUCC} OR NOT (${CMAKE_SYSTEM_PROCESSOR} MATCHES "86")) @@ -151,7 +159,7 @@ if (ENABLE_BACKTRACE) check_library_exists (bfd bfd_init "" HAVE_BFD_LIB) check_include_file(bfd.h HAVE_BFD_H) if (HAVE_BFD_LIB AND HAVE_BFD_H) - set (HAVE_BFD 1) + set (HAVE_BFD True) message (STATUS "Found GNU bfd headers and libs, enabling symbol ") message (STATUS "resolve in backtraces.") elseif (NOT HAVE_BFD_LIB) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 7d0ef6126cd267aab30b685564bdd176525f2fa7..391c0184a4a02bf8c3208f1338133fcf6d8b932d 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -3,8 +3,12 @@ # add_library(ev tarantool_ev.c) -set_source_files_properties(tarantool_ev.c - PROPERTIES COMPILE_FLAGS "-Wno-unused-result") +check_c_compiler_flag ("-Wno-unused-result" gcc_has_wno_unused_result) + +if (gcc_has_wno_unused_result) + set_source_files_properties(tarantool_ev.c + PROPERTIES COMPILE_FLAGS "-Wno-unused-result") +endif() if (TARGET_OS_LINUX) # diff --git a/core/log_io.c b/core/log_io.c index 83518929fdccf83761860138ecbead8629ed0be8..345c8e94c41873366de40e76b83fad421d425a8b 100644 --- a/core/log_io.c +++ b/core/log_io.c @@ -573,7 +573,9 @@ inprogress_log_rename(char *filename) assert(strcmp(suffix, inprogress_suffix) == 0); /* Create a new filename without '.inprogress' suffix. */ - new_filename = strndupa(filename, suffix - filename); + new_filename = alloca(suffix - filename + 1); + memcpy(new_filename, filename, suffix - filename); + new_filename[suffix - filename] = '\0'; if (rename(filename, new_filename) != 0) { say_syserror("can't rename %s to %s", filename, new_filename); @@ -593,7 +595,8 @@ inprogress_log_unlink(char *filename) assert(strcmp(suffix, inprogress_suffix) == 0); #endif if (unlink(filename) != 0) { - if (errno == ENONET) + /* Don't panic if there is no such file. */ + if (errno == ENOENT) return 0; say_syserror("can't unlink %s", filename); diff --git a/core/tarantool.c b/core/tarantool.c index 6cdecbf398344d8dabe1db3c26f7d2daf71cb114..16ca3314a7dbd69007ead73adc12aef695d8b263 100644 --- a/core/tarantool.c +++ b/core/tarantool.c @@ -62,6 +62,7 @@ char *cfg_filename_fullpath = NULL; struct tbuf *cfg_out = NULL; char *binary_filename; struct tarantool_cfg cfg; +struct recovery_state *recovery_state; bool init_storage, booting = true; @@ -267,6 +268,13 @@ create_pid(void) f = fopen(cfg.pid_file, "a+"); if (f == NULL) panic_syserror("can't open pid file"); + /* + * fopen() is not guaranteed to set the seek position to + * the beginning of file according to ANSI C (and, e.g., + * on FreeBSD. + */ + if (fseeko(f, 0, SEEK_SET) != 0) + panic_syserror("can't fseek to the beginning of pid file"); if (fgets(buf, sizeof(buf), f) != NULL && strlen(buf) > 0) { pid = strtol(buf, NULL, 10); @@ -274,7 +282,8 @@ create_pid(void) panic("the daemon is already running"); else say_info("updating a stale pid file"); - fseeko(f, 0, SEEK_SET); + if (fseeko(f, 0, SEEK_SET) != 0) + panic_syserror("can't fseek to the beginning of pid file"); if (ftruncate(fileno(f), 0) == -1) panic_syserror("ftruncate(`%s')", cfg.pid_file); } @@ -313,6 +322,17 @@ main(int argc, char **argv) #endif const char *cfg_paramname = NULL; +#ifndef HAVE_LIBC_STACK_END +/* + * GNU libc provides a way to get at the top of the stack. This + * is, of course, not standard and doesn't work on non-GNU + * systems, such as FreeBSD. But as far as we're concerned, argv + * is at the top of the main thread's stack, so save the address + * of it. + */ + __libc_stack_end = (void*) &argv; +#endif + master_pid = getpid(); stat_init(); palloc_init(); @@ -405,27 +425,6 @@ main(int argc, char **argv) panic("can't load config:" "%.*s", cfg_out->len, (char *)cfg_out->data); -#ifdef STORAGE - if (gopt_arg(opt, 'C', &cat_filename)) { - initialize_minimal(); - if (access(cat_filename, R_OK) == -1) { - say_syserror("access(\"%s\")", cat_filename); - exit(EX_OSFILE); - } - return mod_cat(cat_filename); - } - - if (gopt(opt, 'I')) { - init_storage = true; - initialize_minimal(); - mod_init(); - next_lsn(recovery_state, 1); - confirm_lsn(recovery_state, 1); - snapshot_save(recovery_state, mod_snapshot); - exit(EXIT_SUCCESS); - } -#endif - if (gopt_arg(opt, 'g', &cfg_paramname)) { tarantool_cfg_iterator_t *i; char *key, *value; @@ -483,6 +482,27 @@ main(int argc, char **argv) #endif } +#ifdef STORAGE + if (gopt_arg(opt, 'C', &cat_filename)) { + initialize_minimal(); + if (access(cat_filename, R_OK) == -1) { + say_syserror("access(\"%s\")", cat_filename); + exit(EX_OSFILE); + } + return mod_cat(cat_filename); + } + + if (gopt(opt, 'I')) { + init_storage = true; + initialize_minimal(); + mod_init(); + next_lsn(recovery_state, 1); + confirm_lsn(recovery_state, 1); + snapshot_save(recovery_state, mod_snapshot); + exit(EXIT_SUCCESS); + } +#endif + if (gopt(opt, 'D')) daemonize(1, 1); diff --git a/core/util.c b/core/util.c index 679ea8c1e7600305e093911b6dfd0054bd7158ab..8184fb418b4775d9f79233147dc013a080b92043 100644 --- a/core/util.c +++ b/core/util.c @@ -42,6 +42,10 @@ #include <fiber.h> #include "say.h" +#ifndef HAVE_LIBC_STACK_END +void *__libc_stack_end; +#endif + void close_all_xcpt(int fdc, ...) { diff --git a/include/config.h.cmake b/include/config.h.cmake index cadf475ba9ba2d40add64417f94cb54efa300d49..e8cad3c90d9f6cdabec939d31d50122ad853aaa1 100644 --- a/include/config.h.cmake +++ b/include/config.h.cmake @@ -31,6 +31,10 @@ * Set if the system has bfd.h header and GNU bfd library. */ #cmakedefine HAVE_BFD 1 +/* + * Set if this is a GNU system and libc has __libc_stack_end. + */ +#cmakedefine HAVE_LIBC_STACK_END 1 /* * vim: syntax=c */ diff --git a/include/log_io.h b/include/log_io.h index 5c7f4fabe39301d7cad553b752aa1c4267329b03..34b0b4ce5f60321b1d0c1e6e6ff0ce21808c0d34 100644 --- a/include/log_io.h +++ b/include/log_io.h @@ -97,7 +97,7 @@ struct recovery_state { bool finalize; - /* pointer to user supplied custom data */ + /* Points to module-specific state */ void *data; }; diff --git a/include/tarantool.h b/include/tarantool.h index c317b01c87bb20e0619e182ff1df93138efeb2e2..cc839a8eacd5150b63d4f04e10dd754e81a20b66 100644 --- a/include/tarantool.h +++ b/include/tarantool.h @@ -30,7 +30,7 @@ #include <util.h> #include <log_io.h> -struct recovery_state *recovery_state; +extern struct recovery_state *recovery_state; void mod_init(void); struct tarantool_cfg; i32 mod_check_config(struct tarantool_cfg *conf); diff --git a/test/box/args.result b/test/box/args.result index 7320ce65eb4e3aee5b925d090dba980f8d134d38..91937f0c5d40f92871593e66bd58b54cc5436dfc 100644 --- a/test/box/args.result +++ b/test/box/args.result @@ -65,3 +65,18 @@ tarantool_box --version tarantool_box -V 1.minor.patch-<rev>-<commit> +# +# A test case for Bug#726778 "Gopt broke wal_dir and snap_dir: they are no +# longer relative to work_dir". +# https://bugs.launchpad.net/tarantool/+bug/726778 +# After addition of gopt(), we started to chdir() to the working +# directory after option parsing. +# Verify that this is not the case, and snap_dir and xlog_dir +# can be relative to work_dir. + +tarantool_silverbox --config=bug726778.cfg --init-storage +tarantool_silverbox: namespace 0 successfully configured +tarantool_silverbox: creating `snapshots/00000000000000000001.snap.inprogress' +tarantool_silverbox: saving snapshot `snapshots/00000000000000000001.snap' +tarantool_silverbox: done + diff --git a/test/box/args.test b/test/box/args.test index fa2595804f4ed3fdf55572e6f2c929573f3a0867..5648a8704111a014690d6fe78f526970ea6d7fe0 100644 --- a/test/box/args.test +++ b/test/box/args.test @@ -13,3 +13,31 @@ sys.stdout.push_filter("(\d)\.\d\.\d(-\d+-\w+)?", "\\1.minor.patch-<rev>-<commit server.test_option("--version") server.test_option("-V ") sys.stdout.pop_filter() + +print """# +# A test case for Bug#726778 "Gopt broke wal_dir and snap_dir: they are no +# longer relative to work_dir". +# https://bugs.launchpad.net/tarantool/+bug/726778 +# After addition of gopt(), we started to chdir() to the working +# directory after option parsing. +# Verify that this is not the case, and snap_dir and xlog_dir +# can be relative to work_dir. +""" +import shutil +shutil.rmtree(os.path.join(vardir, "bug726778"), True) +cfg = os.path.join(vardir, "bug726778.cfg") +os.mkdir(os.path.join(vardir, "bug726778")) +os.mkdir(os.path.join(vardir, "bug726778/snapshots")) +os.mkdir(os.path.join(vardir, "bug726778/xlogs")) + +os.symlink(os.path.abspath("box/bug726778.cfg"), cfg) + +sys.stdout.push_filter("(/\S+)+/tarantool", "tarantool") +server.test_option("--config=bug726778.cfg --init-storage") +sys.stdout.pop_filter() + +os.unlink(cfg) +shutil.rmtree(os.path.join(vardir, "bug726778")) + +# Args filter cleanup +# vim: syntax=python diff --git a/test/box/bug726778.cfg b/test/box/bug726778.cfg new file mode 100644 index 0000000000000000000000000000000000000000..449c3986fec792578763065a20655a9131ee8ebf --- /dev/null +++ b/test/box/bug726778.cfg @@ -0,0 +1,27 @@ +# +# Used in args.test +# +slab_alloc_arena = 0.1 + +pid_file = "box.pid" + +work_dir = "bug726778" +snap_dir = "snapshots" +wal_dir = "xlogs" + +# Use -a not -a to work correctly on FreeBSD +# +logger="tee -a tarantool.log" + +primary_port = 33013 +secondary_port = 33014 +admin_port = 33015 + +rows_per_wal = 50 + +namespace[0].enabled = 1 +namespace[0].index[0].type = "HASH" +namespace[0].index[0].unique = 1 +namespace[0].index[0].key_field[0].fieldno = 0 +namespace[0].index[0].key_field[0].type = "NUM" + diff --git a/test/box/show.result b/test/box/show.result index 0811fbee1851e36fd991371c7f32fc0354300054..53f2d43cef6f59e3852ba4cc28392c3c335955f1 100644 --- a/test/box/show.result +++ b/test/box/show.result @@ -35,7 +35,7 @@ configuration: slab_alloc_factor: "2" work_dir: (null) pid_file: "box.pid" - logger: "tee --append tarantool.log" + logger: "tee -a tarantool.log" logger_nonblock: "1" io_collect_interval: "0" backlog: "1024" diff --git a/test/box/tarantool.cfg b/test/box/tarantool.cfg index d7cd0fe80ccd4940e6b324918043eabbf43d45a9..67438804646d0b37577ac35932d98eced24e6c66 100644 --- a/test/box/tarantool.cfg +++ b/test/box/tarantool.cfg @@ -2,7 +2,10 @@ slab_alloc_arena = 0.1 pid_file = "box.pid" -logger="tee --append tarantool.log" + +# Use -a not -a to work correctly on FreeBSD +# +logger="tee -a tarantool.log" primary_port = 33013 secondary_port = 33014 diff --git a/test/box/tarantool_bad2.cfg b/test/box/tarantool_bad2.cfg index 0d03bfde3b38b7e1cce9c5d2b2a40811060bbddf..699a08bcd133632fc25b7861ea50945efaec1e8c 100644 --- a/test/box/tarantool_bad2.cfg +++ b/test/box/tarantool_bad2.cfg @@ -2,7 +2,7 @@ slab_alloc_arena = 0.1 pid_file = "box.pid" -logger="tee --append tarantool.log" +logger="tee -a tarantool.log" #primary_port = 33013 secondary_port = 33014 diff --git a/test/box/tarantool_bad3.cfg b/test/box/tarantool_bad3.cfg index 8c1d14c3c6e43ed63617f14700c5f8c2b2719ff7..934acbe01dca14b1fe733f5bfad0a06e825c8251 100644 --- a/test/box/tarantool_bad3.cfg +++ b/test/box/tarantool_bad3.cfg @@ -2,7 +2,7 @@ slab_alloc_arena = 0.1 pid_file = "box.pid" -logger="tee --append tarantool.log" +logger="tee -a tarantool.log" primary_port = 33013 secondary_port = 33014 diff --git a/test/box/tarantool_bad4.cfg b/test/box/tarantool_bad4.cfg index 67b9c893b0ae0e5f691d090a1bf3a6150648a876..305de0e9a6fd4d62f35427beb53aa7f35d8ddb15 100644 --- a/test/box/tarantool_bad4.cfg +++ b/test/box/tarantool_bad4.cfg @@ -2,7 +2,7 @@ slab_alloc_arena = 0.1 pid_file = "box.pid" -logger="tee --append tarantool.log" +logger="tee -a tarantool.log" primary_port = 33013 secondary_port = 33014 diff --git a/test/box/tarantool_bad5.cfg b/test/box/tarantool_bad5.cfg index 1390839277b1fa49ed953c4aef3d73c269080a9b..7854bd4d37d32105a57a8654e0e27fe950ba5851 100644 --- a/test/box/tarantool_bad5.cfg +++ b/test/box/tarantool_bad5.cfg @@ -2,7 +2,7 @@ slab_alloc_arena = 0.1 pid_file = "box.pid" -logger="tee --append tarantool.log" +logger="tee -a tarantool.log" primary_port = 33013 secondary_port = 33014 diff --git a/test/box/tarantool_good.cfg b/test/box/tarantool_good.cfg index d7cd0fe80ccd4940e6b324918043eabbf43d45a9..32f2c827c3228404bf64dff3a2a6fec58b0794a7 100644 --- a/test/box/tarantool_good.cfg +++ b/test/box/tarantool_good.cfg @@ -2,7 +2,7 @@ slab_alloc_arena = 0.1 pid_file = "box.pid" -logger="tee --append tarantool.log" +logger="tee -a tarantool.log" primary_port = 33013 secondary_port = 33014