From: Date: November 19 2008 10:52am Subject: bzr commit into mysql-5.1 branch (msvensson:2744) Bug#40498 List-Archive: http://lists.mysql.com/commits/59170 X-Bug: 40498 Message-Id: <20081119095209.DF2A913412A@pilot> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///home/msvensson/mysql/bug40498/6.3/ 2744 Magnus Svensson 2008-11-19 Bug#40498 MGM C API calls "Exit" if connection to the managment server is lost - Install SIGPIPE handler to catch broken pipe error that occurs when writing to a closed or rest socket - Add function 'ndb_mgm_set_ignore_sigpipe' making it possible to avoid that mgmapi installs SIGPIPE handler added: storage/ndb/test/ndbapi/testMgmDisconnect.c modified: storage/ndb/include/mgmapi/mgmapi.h storage/ndb/src/mgmapi/mgmapi.cpp storage/ndb/src/mgmclient/CommandInterpreter.cpp storage/ndb/src/mgmclient/main.cpp storage/ndb/test/ndbapi/Makefile.am per-file messages: storage/ndb/include/mgmapi/mgmapi.h Add 'ndb_mgm_set_ignore_sigpipe' storage/ndb/src/mgmapi/mgmapi.cpp Add 'ndb_mgm_set_ignore_sigpipe' Add extra field "ignore_sigpip" to ndb_mgm_handle storage/ndb/src/mgmclient/CommandInterpreter.cpp Use application defined SIGPIPE handler in ndb_mgm client. Tell mgmapi not to installit's default SIGPIPE handler storage/ndb/src/mgmclient/main.cpp Add comment describing how "nbd_mgm" is using it's own SIGPIPE handler storage/ndb/test/ndbapi/Makefile.am Add testMgmDisconnect storage/ndb/test/ndbapi/testMgmDisconnect.c Add testMgmDisconnect === modified file 'storage/ndb/include/mgmapi/mgmapi.h' --- a/storage/ndb/include/mgmapi/mgmapi.h 2008-08-07 03:45:20 +0000 +++ b/storage/ndb/include/mgmapi/mgmapi.h 2008-11-19 09:52:01 +0000 @@ -405,6 +405,23 @@ extern "C" { */ void ndb_mgm_set_name(NdbMgmHandle handle, const char *name); + /** + * Set 'ignore_sigpipe' behaviour + * + * The mgmapi will by default install a signal handler + * that ignores all SIGPIPE signals that might occur when + * writing to an already closed or reset socket. An application + * that wish to use its own handler for SIGPIPE should call this + * function after 'ndb_mgm_create_handle' and before + * 'ndb_mgm_connect'(where the signal handler is installed) + * + * @param handle Management handle + * @param val Value + * 0 - Don't ignore SIGPIPE + * 1 - Ignore SIGPIPE(default) + */ + int ndb_mgm_set_ignore_sigpipe(NdbMgmHandle handle, int val); + /** @} *********************************************************************/ /** * @name Functions: Connect/Disconnect Management Server === modified file 'storage/ndb/src/mgmapi/mgmapi.cpp' --- a/storage/ndb/src/mgmapi/mgmapi.cpp 2008-10-31 15:22:39 +0000 +++ b/storage/ndb/src/mgmapi/mgmapi.cpp 2008-11-19 09:52:01 +0000 @@ -106,6 +106,7 @@ struct ndb_mgm_handle { int mgmd_version_minor; int mgmd_version_build; char * m_bindaddress; + bool ignore_sigpipe; }; #define SET_ERROR(h, e, s) setError(h, e, __LINE__, s) @@ -189,6 +190,7 @@ ndb_mgm_create_handle() h->errstream = stdout; h->m_name = 0; h->m_bindaddress = 0; + h->ignore_sigpipe = true; strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE); @@ -252,6 +254,19 @@ ndb_mgm_set_bindaddress(NdbMgmHandle han DBUG_RETURN(0); } +extern "C" +int +ndb_mgm_set_ignore_sigpipe(NdbMgmHandle handle, int val) +{ + CHECK_HANDLE(handle, -1); + if (handle->connected){ + SET_ERROR(handle, EINVAL, "Can't change 'ignore_sigpipe' while connected"); + return -1; + } + handle->ignore_sigpipe = (val != 0); + return 0; +} + /** * Destroy a handle */ @@ -516,6 +531,11 @@ ndb_mgm_connect(NdbMgmHandle handle, int #endif char buf[1024]; +#if defined SIGPIPE && !defined _WIN32 + if (handle->ignore_sigpipe) + (void)signal(SIGPIPE, SIG_IGN); +#endif + /** * Do connect */ === modified file 'storage/ndb/src/mgmclient/CommandInterpreter.cpp' --- a/storage/ndb/src/mgmclient/CommandInterpreter.cpp 2008-03-14 13:34:05 +0000 +++ b/storage/ndb/src/mgmclient/CommandInterpreter.cpp 2008-11-19 09:52:01 +0000 @@ -941,13 +941,25 @@ CommandInterpreter::connect(bool interac m_mgmsrv = ndb_mgm_create_handle(); if(m_mgmsrv == NULL) { - ndbout_c("Cannot create handle to management server."); + ndbout_c("Can't create handle to management server."); + exit(-1); + } + if (ndb_mgm_set_ignore_sigpipe(m_mgmsrv, 0)) { + ndbout_c("Can't set 'ignore_sigpipe', error: %d - %s", + ndb_mgm_get_latest_error(m_mgmsrv), + ndb_mgm_get_latest_error_desc(m_mgmsrv)); exit(-1); } if (interactive) { m_mgmsrv2 = ndb_mgm_create_handle(); if(m_mgmsrv2 == NULL) { - ndbout_c("Cannot create 2:nd handle to management server."); + ndbout_c("Can't create 2:nd handle to management server."); + exit(-1); + } + if (ndb_mgm_set_ignore_sigpipe(m_mgmsrv2, 0)) { + ndbout_c("Can't set 'ignore_sigpipe', error: %d - %s", + ndb_mgm_get_latest_error(m_mgmsrv2), + ndb_mgm_get_latest_error_desc(m_mgmsrv2)); exit(-1); } } @@ -2278,7 +2290,7 @@ CommandInterpreter::executeStatus(int pr cl = ndb_mgm_get_status2(m_mgmsrv, all ? types : 0); if(cl == NULL) { - ndbout_c("Cannot get status of node %d.", processId); + ndbout_c("Can't get status of node %d.", processId); printError(); return -1; } @@ -2396,7 +2408,7 @@ CommandInterpreter::executeReport(int pr struct ndb_mgm_cluster_state *cl = ndb_mgm_get_status(m_mgmsrv); if (cl == NULL) { - ndbout_c("Cannot get status of node %d.", processId); + ndbout_c("Can't get status of node %d.", processId); printError(); return -1; } === modified file 'storage/ndb/src/mgmclient/main.cpp' --- a/storage/ndb/src/mgmclient/main.cpp 2007-06-17 15:21:27 +0000 +++ b/storage/ndb/src/mgmclient/main.cpp 2008-11-19 09:52:01 +0000 @@ -55,7 +55,9 @@ handler(int sig) * Will happen when connection to mgmsrv is broken * Reset connected flag */ - com->disconnect(); + printf("Got SIGPIPE!\n"); + if (com) + com->disconnect(); break; } DBUG_VOID_RETURN; @@ -154,6 +156,10 @@ int main(int argc, char** argv){ prompt= 0; } + // Install our own signal handler for SIGPIPE that calls + // 'Ndb_mgmclient' disconnect. In order to avoid that the + // mgmapi installs its own SIGPIPE handler, the Ndb_mgmclient will + // use 'ndb_mgm_set_ignore_sigpipe(handle, 0)' signal(SIGPIPE, handler); com = new Ndb_mgmclient(opt_connect_str,1); int ret= 0; === modified file 'storage/ndb/test/ndbapi/Makefile.am' --- a/storage/ndb/test/ndbapi/Makefile.am 2008-10-30 15:15:48 +0000 +++ b/storage/ndb/test/ndbapi/Makefile.am 2008-11-19 09:52:01 +0000 @@ -59,7 +59,8 @@ ndbapi_50compat1 \ testNDBT \ testReconnect \ NdbRepStress \ -msa +msa \ +testMgmDisconnect EXTRA_PROGRAMS = \ test_event \ === added file 'storage/ndb/test/ndbapi/testMgmDisconnect.c' --- a/storage/ndb/test/ndbapi/testMgmDisconnect.c 1970-01-01 00:00:00 +0000 +++ b/storage/ndb/test/ndbapi/testMgmDisconnect.c 2008-11-19 09:52:01 +0000 @@ -0,0 +1,63 @@ +/* Copyright (C) 2008 Sun Microsystems Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include +#include + +#include + +int main() +{ + NdbMgmHandle handle= ndb_mgm_create_handle(); + + while(1==1){ + if (ndb_mgm_connect(handle,0,0,0) == -1){ + printf("connect failed, error: '%d: %s'\n", + ndb_mgm_get_latest_error(handle), + ndb_mgm_get_latest_error_desc(handle)); + sleep(1); + continue; + } + + while(ndb_mgm_is_connected(handle) != 0){ + struct ndb_mgm_cluster_state *state= ndb_mgm_get_status(handle); + + if(state==NULL){ + printf("ndb_mgm_get_status failed, error: '%d: %s', line: %d\n", + ndb_mgm_get_latest_error(handle), + ndb_mgm_get_latest_error_desc(handle), + ndb_mgm_get_latest_error_line(handle)); + continue; + } + + int i= 0; + for(i=0; i < state->no_of_nodes; i++) + { + struct ndb_mgm_node_state *node_state= &state->node_states[i]; + printf("node with ID=%d ", node_state->node_id); + + if(node_state->version != 0) + printf("connected\n"); + else + printf("not connected\n"); + } + free((void*)state); + } + } + + ndb_mgm_destroy_handle(&handle); + return 1; +}