From 809ab487b2f6248592d068059a13ef6f2679f558 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Mon, 1 Oct 2018 13:13:40 +0300 Subject: [PATCH 01/13] Update version number for 2.2 --- VERSION22.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION22.cmake b/VERSION22.cmake index 074273e32..2090185d0 100644 --- a/VERSION22.cmake +++ b/VERSION22.cmake @@ -5,7 +5,7 @@ set(MAXSCALE_VERSION_MAJOR "2" CACHE STRING "Major version") set(MAXSCALE_VERSION_MINOR "2" CACHE STRING "Minor version") -set(MAXSCALE_VERSION_PATCH "15" CACHE STRING "Patch version") +set(MAXSCALE_VERSION_PATCH "16" CACHE STRING "Patch version") # This should only be incremented if a package is rebuilt set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number") From ee4590064889f2b4859e0705c9e2438f5b5ef4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 26 Sep 2018 20:21:17 +0300 Subject: [PATCH 02/13] Remove network variable export file after use Otherwise the file is left in the current working directory. --- maxscale-system-test/mdbci/set_env.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/maxscale-system-test/mdbci/set_env.sh b/maxscale-system-test/mdbci/set_env.sh index 75950f7fb..46893015d 100644 --- a/maxscale-system-test/mdbci/set_env.sh +++ b/maxscale-system-test/mdbci/set_env.sh @@ -23,6 +23,7 @@ export node_N=`cat "$MDBCI_VM_PATH/$config_name"_network_config | grep node | gr export maxscale_N=`cat "$MDBCI_VM_PATH/$config_name"_network_config | grep maxscale | grep network | wc -l` sed "s/^/export /g" "$MDBCI_VM_PATH/$config_name"_network_config > "$curr_dir"/"$config_name"_network_config_export source "$curr_dir"/"$config_name"_network_config_export +rm "$curr_dir"/"$config_name"_network_config_export # User name and Password for Master/Slave replication setup (should have all PRIVILEGES) From 93d866c6a75dab8f88c617706072fc6dbf66d890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Thu, 27 Sep 2018 18:56:15 +0300 Subject: [PATCH 03/13] MXS-2073: Add missing TCP_NODELAY for client sockets The client connections had the Nagle algorithm enabled which could cause bad performance with smaller workloads. The common network configuration code in utils.cc, currently used by the backend connections, sets it properly. --- include/maxscale/limits.h | 26 ++++++-------------------- include/maxscale/utils.h | 14 ++++++++++++++ server/core/dcb.cc | 16 +--------------- server/core/utils.cc | 11 ++++++----- 4 files changed, 27 insertions(+), 40 deletions(-) diff --git a/include/maxscale/limits.h b/include/maxscale/limits.h index c167bb044..90395c1e5 100644 --- a/include/maxscale/limits.h +++ b/include/maxscale/limits.h @@ -24,32 +24,18 @@ MXS_BEGIN_DECLS /** - * MXS_BACKEND_SO_RCVBUF + * MXS_SO_RCVBUF * - * The value used when setting SO_RCVBUF of backend sockets. + * The size of the network input buffer. */ -#define MXS_BACKEND_SO_RCVBUF (128 * 1024) +#define MXS_SO_RCVBUF_SIZE (128 * 1024) /** - * MXS_BACKEND_SO_SNDBUF + * MXS_SO_SNDBUF * - * The value used when setting SO_SNDBUF of backend sockets. + * The size of the network output buffer. */ -#define MXS_BACKEND_SO_SNDBUF (128 * 1024) - -/** - * MXS_CLIENT_SO_RCVBUF - * - * The value used when setting SO_RCVBUF of client sockets. - */ -#define MXS_CLIENT_SO_RCVBUF (128 * 1024) - -/** - * MXS_CLIENT_SO_SNDBUF - * - * The value used when setting SO_SNDBUF of client sockets. - */ -#define MXS_CLIENT_SO_SNDBUF (128 * 1024) +#define MXS_SO_SNDBUF_SIZE (128 * 1024) /** * MXS_MAX_NW_READ_BUFFER_SIZE diff --git a/include/maxscale/utils.h b/include/maxscale/utils.h index 4e0036a06..0fa878f38 100644 --- a/include/maxscale/utils.h +++ b/include/maxscale/utils.h @@ -46,6 +46,20 @@ enum mxs_socket_type bool utils_init(); /*< Call this first before using any other function */ void utils_end(); +/** + * Configure network socket options + * + * This is a helper function for setting various socket options that are always wanted for all types + * of connections. It sets the socket into nonblocking mode, configures sndbuf and rcvbuf sizes + * and sets TCP_NODELAY (no Nagle algorithm). + * + * @param so Socket to configure + * @param type Socket type + * + * @return True if configuration was successful + */ +bool configure_network_socket(int so, int type); + /** * @brief Create a network socket and a socket configuration * diff --git a/server/core/dcb.cc b/server/core/dcb.cc index 3036a3098..945bacb9b 100644 --- a/server/core/dcb.cc +++ b/server/core/dcb.cc @@ -2369,21 +2369,7 @@ dcb_accept(DCB *dcb) { dcb->stats.n_accepts++; - /* set nonblocking */ - sendbuf = MXS_CLIENT_SO_SNDBUF; - - if (setsockopt(c_sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, optlen) != 0) - { - MXS_ERROR("Failed to set socket options: %d, %s", errno, mxs_strerror(errno)); - } - - sendbuf = MXS_CLIENT_SO_RCVBUF; - - if (setsockopt(c_sock, SOL_SOCKET, SO_RCVBUF, &sendbuf, optlen) != 0) - { - MXS_ERROR("Failed to set socket options: %d, %s", errno, mxs_strerror(errno)); - } - setnonblocking(c_sock); + configure_network_socket(c_sock, client_conn.ss_family); client_dcb = dcb_alloc(DCB_ROLE_CLIENT_HANDLER, dcb->listener); diff --git a/server/core/utils.cc b/server/core/utils.cc index ccab2f6be..24928eefa 100644 --- a/server/core/utils.cc +++ b/server/core/utils.cc @@ -942,17 +942,18 @@ void utils_end() SPINLOCK tmplock = SPINLOCK_INIT; -static bool configure_network_socket(int so) +bool configure_network_socket(int so, int type) { - int sndbufsize = MXS_BACKEND_SO_SNDBUF; - int rcvbufsize = MXS_BACKEND_SO_RCVBUF; + int sndbufsize = MXS_SO_SNDBUF_SIZE; + int rcvbufsize = MXS_SO_RCVBUF_SIZE; int one = 1; if (setsockopt(so, SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(sndbufsize)) != 0 || setsockopt(so, SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(rcvbufsize)) != 0 || - setsockopt(so, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) != 0) + (type != AF_UNIX && setsockopt(so, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) != 0)) { MXS_ERROR("Failed to set socket option: %d, %s.", errno, mxs_strerror(errno)); + ss_dassert(!true); return false; } @@ -1022,7 +1023,7 @@ int open_network_socket(enum mxs_socket_type type, struct sockaddr_storage *addr freeaddrinfo(ai); - if ((type == MXS_SOCKET_NETWORK && !configure_network_socket(so)) || + if ((type == MXS_SOCKET_NETWORK && !configure_network_socket(so, addr->ss_family)) || (type == MXS_SOCKET_LISTENER && !configure_listener_socket(so))) { close(so); From f65c890287f2a002cc471fa518f460d6b13f6951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Thu, 27 Sep 2018 00:11:59 +0300 Subject: [PATCH 04/13] MXS-2049: Forward client credentials to backend server Instead of requesting another set of credentials, the client credentials are simply forwarded to the backend MariaDB server. --- .../GSSAPIBackendAuth/gssapi_backend_auth.c | 65 ++++--------------- 1 file changed, 11 insertions(+), 54 deletions(-) diff --git a/server/modules/authenticator/GSSAPI/GSSAPIBackendAuth/gssapi_backend_auth.c b/server/modules/authenticator/GSSAPI/GSSAPIBackendAuth/gssapi_backend_auth.c index bce684ba7..776f87808 100644 --- a/server/modules/authenticator/GSSAPI/GSSAPIBackendAuth/gssapi_backend_auth.c +++ b/server/modules/authenticator/GSSAPI/GSSAPIBackendAuth/gssapi_backend_auth.c @@ -59,70 +59,27 @@ void gssapi_backend_auth_free(void *data) static bool send_new_auth_token(DCB *dcb) { bool rval = false; - OM_uint32 major = 0, minor = 0; - gss_ctx_id_t handle = NULL; - gss_buffer_desc in = {0, 0}; - gss_buffer_desc out = {0, 0}; - gss_buffer_desc target = {0, 0}; - gss_name_t princ = GSS_C_NO_NAME; gssapi_auth_t *auth = (gssapi_auth_t*)dcb->authenticator_data; + MYSQL_session *ses = (MYSQL_session*)dcb->session->client_dcb->data; + GWBUF *buffer = gwbuf_alloc(MYSQL_HEADER_LEN + ses->auth_token_len); - /** The service principal name is sent by the backend server */ - target.value = auth->principal_name; - target.length = auth->principal_name_len + 1; + // This function actually just forwards the client's token to the backend server - /** Convert the name into GSSAPI format */ - major = gss_import_name(&minor, &target, GSS_C_NT_USER_NAME, &princ); - - if (GSS_ERROR(major)) + if (buffer) { - report_error(major, minor); - } + uint8_t *data = (uint8_t*)GWBUF_DATA(buffer); + gw_mysql_set_byte3(data, ses->auth_token_len); + data += 3; + *data++ = ++auth->sequence; + memcpy(data, ses->auth_token, ses->auth_token_len); - /** Request the token for the service */ - major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, - &handle, princ, GSS_C_NO_OID, 0, 0, - GSS_C_NO_CHANNEL_BINDINGS, &in, NULL, &out, 0, 0); - if (GSS_ERROR(major)) - { - report_error(major, minor); - } - else - { - /** We successfully requested the token, send it to the backend server */ - GWBUF *buffer = gwbuf_alloc(MYSQL_HEADER_LEN + out.length); - - if (buffer) + if (dcb_write(dcb, buffer)) { - uint8_t *data = (uint8_t*)GWBUF_DATA(buffer); - gw_mysql_set_byte3(data, out.length); - data += 3; - *data++ = ++auth->sequence; - memcpy(data, out.value, out.length); - - if (dcb_write(dcb, buffer)) - { - rval = true; - } - } - - major = gss_delete_sec_context(&minor, &handle, &in); - - if (GSS_ERROR(major)) - { - report_error(major, minor); - } - - major = gss_release_name(&minor, &princ); - - if (GSS_ERROR(major)) - { - report_error(major, minor); + rval = true; } } return rval; - } /** From d87d462c767b3098a45dc5475599acfe59581f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Fri, 28 Sep 2018 10:24:17 +0300 Subject: [PATCH 05/13] MXS-2049: Update GSSAPI documentation Corrected the documentation and provided more details on how to configure the authenticator. --- .../Authenticators/GSSAPI-Authenticator.md | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/Documentation/Authenticators/GSSAPI-Authenticator.md b/Documentation/Authenticators/GSSAPI-Authenticator.md index ce434d5b7..ab8765587 100644 --- a/Documentation/Authenticators/GSSAPI-Authenticator.md +++ b/Documentation/Authenticators/GSSAPI-Authenticator.md @@ -12,29 +12,32 @@ _GSSAPIBackendAuth_ module implements the backend authentication. For Unix systems, the usual GSSAPI implementation is Kerberos. This is a short guide on how to set up Kerberos for MaxScale. -The first step is to create a new principal for MaxScale. This can be done with -the _kadmin_ or _kadmin.local_ tools. +The first step is to configure MariaDB to use GSSAPI authentication. The MariaDB +documentation for the +[GSSAPI Authentication Plugin](https://mariadb.com/kb/en/mariadb/gssapi-authentication-plugin/) +is a good example on how to set it up. + +The next step is to copy the keytab file from the server where MariaDB is +installed to the server where MaxScale is located. The keytab file must be +placed in the configured default location which almost always is +`/etc/krb5.keytab`. + +To take GSSAPI authentication into use, add the following to the listener. ``` -kadmin.local -q "addprinc -nokey mariadb/example.com@EXAMPLE.COM" +authenticator=GSSAPIAuth +authenticator_options=principal_name=mariadb/localhost.localdomain@EXAMPLE.COM ``` -The `-nokey` option will make the principal a passwordless one. This allows the -_maxscale_ user to acquire a ticket for it without a password being prompted. +Change the principal name to the same value you configured for the MariaDB +server. -The next step is to export this principal into the Kerberos keytab file. +After the listeners are configured, add the following to all servers that use GSSAPI users. ``` -kadmin.local -q "ktadd -k /etc/krb5.keytab -norandkey mariadb/example.com@EXAMPLE.COM" +authenticator=GSSAPIBackendAuth ``` -This adds the _mariadb/example.com@EXAMPLE.COM_ principal into the keytab -file. The `-norandkey` option tells that the password we defined earlier, -i.e. no password at all, should be used instead of a random password. - -The MariaDB documentation for the [GSSAPI Authentication Plugin](https://mariadb.com/kb/en/mariadb/gssapi-authentication-plugin/) -is a good example on how to set up a new principal for the MariaDB server. - ## Authenticator options The client side GSSAPIAuth authenticator supports one option, the service @@ -43,14 +46,12 @@ module has no options. ### `principal_name` -The service principal name to send to the client. This parameter is a -string parameter which is used by the client to request the token. +The service principal name to send to the client. This parameter is a string +parameter which is used by the client to request the token. The default value +for this option is _mariadb/localhost.localdomain_. -The default value for this option is _mariadb/localhost.localdomain_. - -The parameter must be a valid GSSAPI principal name -e.g. `styx/pluto@EXAMPLE.COM`. The principal name can also be defined -without the realm part in which case the default realm will be used. +This parameter *must* be the same as the principal name that the backend MariaDB +server uses. ## Implementation details From c7fc00b3d88a6b2f8f802e73df3eb40df3680d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Sun, 30 Sep 2018 22:47:12 +0300 Subject: [PATCH 06/13] Shorten mxs812_1 Three iterations should be adequate for most cases. --- maxscale-system-test/mxs812_1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maxscale-system-test/mxs812_1.cpp b/maxscale-system-test/mxs812_1.cpp index e3c95b5cc..1f1bf6f31 100644 --- a/maxscale-system-test/mxs812_1.cpp +++ b/maxscale-system-test/mxs812_1.cpp @@ -60,7 +60,7 @@ int main(int argc, char *argv[]) { TestConnections * Test = new TestConnections(argc, argv); Test->set_timeout(300); - int iter = 10; + int iter = 3; Test->repl->execute_query_all_nodes( (char *) "set global max_allowed_packet=10000000"); From 7b5985d6be649db7b9625f553cf42d0a0a689e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 1 Oct 2018 07:01:46 +0300 Subject: [PATCH 07/13] Add missing connect to mxs682_cyrillic The connections were used without connecting. --- maxscale-system-test/mxs682_cyrillic.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/maxscale-system-test/mxs682_cyrillic.cpp b/maxscale-system-test/mxs682_cyrillic.cpp index ade3ad5f9..0a4d83514 100644 --- a/maxscale-system-test/mxs682_cyrillic.cpp +++ b/maxscale-system-test/mxs682_cyrillic.cpp @@ -35,16 +35,21 @@ int main(int argc, char *argv[]) test.stop_timeout(); test.repl->connect(); test.repl->sync_slaves(); + test.repl->disconnect(); test.set_timeout(60); + test.maxscales->connect(); check_val(test.maxscales->conn_rwsplit[0], test); check_val(test.maxscales->conn_master[0], test); check_val(test.maxscales->conn_slave[0], test); + test.maxscales->disconnect(); + nodes->connect(); for (int i = 0; i < test.repl->N; i++) { check_val(nodes->nodes[i], test); } + nodes->disconnect(); return test.global_result; } From 3fd0c2c40752a0ff117f1a0addc92201a1342622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 1 Oct 2018 07:19:19 +0300 Subject: [PATCH 08/13] Stop timeout during slave sync --- maxscale-system-test/mxs1743_rconn_bitmask.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/maxscale-system-test/mxs1743_rconn_bitmask.cpp b/maxscale-system-test/mxs1743_rconn_bitmask.cpp index d32a82a46..815fadce4 100644 --- a/maxscale-system-test/mxs1743_rconn_bitmask.cpp +++ b/maxscale-system-test/mxs1743_rconn_bitmask.cpp @@ -46,8 +46,9 @@ int main(int argc, char** argv) test.try_query(test.repl->nodes[0], "%s", "GRANT ALL ON *.* TO 'mxs1743'@'%'"); test.tprintf("Syncing slaves"); - test.set_timeout(60); + test.stop_timeout(); test.repl->sync_slaves(); + test.set_timeout(60); test.tprintf("Opening new connections to verify readconnroute works"); From 62e5f988c58f9cbbec6d04e6837879452a8532ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 1 Oct 2018 10:01:13 +0300 Subject: [PATCH 09/13] MXS-2075: Redirect stdout and stderr to the log If the log file is successfully opened, both stdout and stderr are redirected to it. This helps catch ASAN reports without having to read the system journal files. As the output is redirected to a file, some of the output was made visible only in non-daemon mode. This helps keep the log file clean and readable. --- server/core/gateway.cc | 28 ++++++++++++++++++++-------- server/core/log_manager.cc | 10 ++++++++++ server/core/skygw_utils.cc | 1 - 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/server/core/gateway.cc b/server/core/gateway.cc index 1d12f879f..06ee47d16 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -350,9 +350,12 @@ static void sigterm_handler(int i) if (n_shutdowns == 1) { - if (write(STDERR_FILENO, shutdown_msg, sizeof(shutdown_msg) - 1) == -1) + if (!daemon_mode) { - printf("Failed to write shutdown message!\n"); + if (write(STDERR_FILENO, shutdown_msg, sizeof(shutdown_msg) - 1) == -1) + { + printf("Failed to write shutdown message!\n"); + } } } else @@ -369,16 +372,22 @@ sigint_handler(int i) if (n_shutdowns == 1) { - if (write(STDERR_FILENO, shutdown_msg, sizeof(shutdown_msg) - 1) == -1) + if (!daemon_mode) { - printf("Failed to write shutdown message!\n"); + if (write(STDERR_FILENO, shutdown_msg, sizeof(shutdown_msg) - 1) == -1) + { + printf("Failed to write shutdown message!\n"); + } } } else if (n_shutdowns == 2) { - if (write(STDERR_FILENO, patience_msg, sizeof(patience_msg) - 1) == -1) + if (!daemon_mode) { - printf("Failed to write shutdown message!\n"); + if (write(STDERR_FILENO, patience_msg, sizeof(patience_msg) - 1) == -1) + { + printf("Failed to write shutdown message!\n"); + } } } else @@ -500,8 +509,11 @@ sigfatal_handler(int i) void *addrs[128]; int count = backtrace(addrs, 128); - // First print the stack trace to stderr as malloc is likely broken - backtrace_symbols_fd(addrs, count, STDERR_FILENO); + if (!daemon_mode) + { + // First print the stack trace to stderr as malloc is likely broken + backtrace_symbols_fd(addrs, count, STDERR_FILENO); + } MXS_ALERT("Fatal: MaxScale " MAXSCALE_VERSION " received fatal signal %d. " "Attempting backtrace.", i); diff --git a/server/core/log_manager.cc b/server/core/log_manager.cc index 4fdf3f4f3..893971e53 100644 --- a/server/core/log_manager.cc +++ b/server/core/log_manager.cc @@ -572,6 +572,10 @@ static bool logmanager_init_nomutex(const char* ident, succ = true; lm->lm_enabled = true; + // Redirect stdout and stderr to the log file + freopen(lm->lm_logfile.lf_full_file_name, "a", stdout); + freopen(lm->lm_logfile.lf_full_file_name, "a", stderr); + return_succ: if (err != 0) { @@ -2155,6 +2159,12 @@ static bool thr_flush_file(logmanager_t *lm, filewriter_t *fwr) LOG_ERROR("MaxScale Log: Error, could not re-open log file %s.\n", lf->lf_full_file_name); } + else + { + // Redirect stdout and stderr to the new log file + freopen(lf->lf_full_file_name, "a", stdout); + freopen(lf->lf_full_file_name, "a", stderr); + } } return true; diff --git a/server/core/skygw_utils.cc b/server/core/skygw_utils.cc index 48c0c6d9e..3b1a6f8fe 100644 --- a/server/core/skygw_utils.cc +++ b/server/core/skygw_utils.cc @@ -839,7 +839,6 @@ void skygw_file_close(skygw_file_t* file) } else { - ss_dfprintf(stderr, "Closed %s\n", file->sf_fname); skygw_file_free(file); } } From 79d1eb19d73beeb409b52ab5102819498685df4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 1 Oct 2018 10:07:37 +0300 Subject: [PATCH 10/13] Disable unit test leak checks for DEB packages The unit tests themselves don't leak memory but some of the core components of MaxScale do. To ignore this, ASAN_OPTIONS needs to be defined. --- BUILD/build_deb_local.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BUILD/build_deb_local.sh b/BUILD/build_deb_local.sh index 0640673ef..1c8c078de 100755 --- a/BUILD/build_deb_local.sh +++ b/BUILD/build_deb_local.sh @@ -16,6 +16,8 @@ make if [[ "$cmake_flags" =~ "BUILD_TESTS" ]] then + # We don't care about memory leaks in the tests (e.g. servers are never freed) + export ASAN_OPTIONS=detect_leaks=0 # All tests must pass otherwise the build is considered a failure ctest --output-on-failure || exit 1 fi From 048aee1fb719a2da47ea2790e447b090479cced9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 1 Oct 2018 10:25:00 +0300 Subject: [PATCH 11/13] Print output of failed Travis tests If a unit test fails, print the output. --- .travis/build_maxscale.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/build_maxscale.sh b/.travis/build_maxscale.sh index 153ccb6e3..94adeb3e0 100644 --- a/.travis/build_maxscale.sh +++ b/.travis/build_maxscale.sh @@ -18,7 +18,7 @@ cd build cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=Y make -make test || exit 1 +ctest --output-on-failure || exit 1 sudo make install sudo ./postinst From 288fbc8c338b80e627d3f533e39baab49e284007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 1 Oct 2018 11:01:09 +0300 Subject: [PATCH 12/13] MXS-2075: Only enable stdout redirection for maxscale The stdout redirection must not be enabled for the other programs as they are not run as daemon processes. --- include/maxscale/log_manager.h | 1 + server/core/gateway.cc | 5 +++++ server/core/log_manager.cc | 17 +++++++++++++---- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/maxscale/log_manager.h b/include/maxscale/log_manager.h index e845d3b77..02c1b4c71 100644 --- a/include/maxscale/log_manager.h +++ b/include/maxscale/log_manager.h @@ -106,6 +106,7 @@ void mxs_log_set_maxlog_enabled(bool enabled); void mxs_log_set_highprecision_enabled(bool enabled); void mxs_log_set_augmentation(int bits); void mxs_log_set_throttling(const MXS_LOG_THROTTLING* throttling); +void mxs_log_redirect_stdout(bool redirect); void mxs_log_get_throttling(MXS_LOG_THROTTLING* throttling); json_t* mxs_logs_to_json(const char* host); diff --git a/server/core/gateway.cc b/server/core/gateway.cc index 06ee47d16..3482315fb 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -1985,6 +1985,11 @@ int main(int argc, char **argv) log_target = MXS_LOG_TARGET_SHMEM; } + if (!to_stdout && daemon_mode) + { + mxs_log_redirect_stdout(true); + } + succp = mxs_log_init(NULL, get_logdir(), log_target); if (!succp) diff --git a/server/core/log_manager.cc b/server/core/log_manager.cc index 893971e53..d625235a4 100644 --- a/server/core/log_manager.cc +++ b/server/core/log_manager.cc @@ -160,6 +160,7 @@ static bool flushall_flag; static bool flushall_started_flag; static bool flushall_done_flag; static HASHTABLE* message_stats; +static bool redirect_stdout = false; /** This is used to detect if the initialization of the log manager has failed * and that it isn't initialized again after a failure has occurred. */ @@ -572,9 +573,12 @@ static bool logmanager_init_nomutex(const char* ident, succ = true; lm->lm_enabled = true; - // Redirect stdout and stderr to the log file - freopen(lm->lm_logfile.lf_full_file_name, "a", stdout); - freopen(lm->lm_logfile.lf_full_file_name, "a", stderr); + if (redirect_stdout) + { + // Redirect stdout and stderr to the log file + freopen(lm->lm_logfile.lf_full_file_name, "a", stdout); + freopen(lm->lm_logfile.lf_full_file_name, "a", stderr); + } return_succ: if (err != 0) @@ -2159,7 +2163,7 @@ static bool thr_flush_file(logmanager_t *lm, filewriter_t *fwr) LOG_ERROR("MaxScale Log: Error, could not re-open log file %s.\n", lf->lf_full_file_name); } - else + else if (redirect_stdout) { // Redirect stdout and stderr to the new log file freopen(lf->lf_full_file_name, "a", stdout); @@ -3131,3 +3135,8 @@ json_t* mxs_logs_to_json(const char* host) return mxs_json_resource(host, MXS_JSON_API_LOGS, data); } + +void mxs_log_redirect_stdout(bool redirect) +{ + redirect_stdout = redirect; +} From dad4f55ee6c540b186d349716f62380882d24761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 1 Oct 2018 12:27:26 +0300 Subject: [PATCH 13/13] Save output of mysqlmon tests Before the tests truncate the log, it can be copied to a backup file. This allows the whole log to be inspected after the test is complete. --- maxscale-system-test/fail_switch_rejoin_common.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/maxscale-system-test/fail_switch_rejoin_common.cpp b/maxscale-system-test/fail_switch_rejoin_common.cpp index ccb6541da..cd03dbbe1 100644 --- a/maxscale-system-test/fail_switch_rejoin_common.cpp +++ b/maxscale-system-test/fail_switch_rejoin_common.cpp @@ -22,7 +22,8 @@ void get_output(TestConnections& test) { test.tprintf("MaxScale output:"); } - output = test.maxscales->ssh_node_output(0, "cat /var/log/maxscale/maxscale.log && " + output = test.maxscales->ssh_node_output(0, + "cat /var/log/maxscale/maxscale.log | tee -a /var/log/maxscale/maxscale_backup.log && " "sudo truncate -s 0 /var/log/maxscale/maxscale.log", true, &ec); if (test.verbose)