mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
03e4b98c7b
into mysql.com:/home/my/mysql-5.0 BitKeeper/etc/ignore: added mysql-test/mysql-test-run-shell client/mysql.cc: Auto merged client/mysql_upgrade.c: Auto merged client/mysqlbinlog.cc: Auto merged client/mysqldump.c: Auto merged client/mysqltest.c: Auto merged client/sql_string.cc: Auto merged client/sql_string.h: Auto merged extra/my_print_defaults.c: Auto merged include/m_ctype.h: Auto merged include/my_pthread.h: Auto merged include/my_sys.h: Auto merged include/my_time.h: Auto merged include/mysql.h: Auto merged libmysql/libmysql.c: Auto merged libmysqld/lib_sql.cc: Auto merged myisam/ft_boolean_search.c: Auto merged myisam/mi_open.c: Auto merged myisam/mi_search.c: Auto merged myisam/mi_unique.c: Auto merged myisam/myisampack.c: Auto merged myisam/rt_index.c: Auto merged myisam/sort.c: Auto merged mysql-test/t/mysql.test: Auto merged mysql-test/t/mysqltest.test: Auto merged mysys/default.c: Auto merged mysys/mf_iocache2.c: Auto merged mysys/mf_keycache.c: Auto merged mysys/my_bitmap.c: Auto merged mysys/sha1.c: Auto merged ndb/include/kernel/signaldata/ArbitSignalData.hpp: Auto merged ndb/include/kernel/signaldata/DictTabInfo.hpp: Auto merged ndb/include/ndbapi/NdbReceiver.hpp: Auto merged ndb/include/transporter/TransporterDefinitions.hpp: Auto merged ndb/include/util/InputStream.hpp: Auto merged ndb/include/util/OutputStream.hpp: Auto merged ndb/include/util/SimpleProperties.hpp: Auto merged ndb/include/util/SocketAuthenticator.hpp: Auto merged ndb/include/util/SocketServer.hpp: Auto merged ndb/src/common/mgmcommon/ConfigRetriever.cpp: Auto merged ndb/src/common/portlib/NdbTick.c: Auto merged ndb/src/common/transporter/SHM_Transporter.cpp: Auto merged ndb/src/common/transporter/TCP_Transporter.cpp: Auto merged ndb/src/common/transporter/TCP_Transporter.hpp: Auto merged ndb/src/common/transporter/Transporter.cpp: Auto merged ndb/src/common/transporter/TransporterRegistry.cpp: Auto merged ndb/src/common/util/Bitmask.cpp: Auto merged ndb/src/common/util/ConfigValues.cpp: Auto merged ndb/src/common/util/File.cpp: Auto merged ndb/src/common/util/Properties.cpp: Auto merged ndb/src/common/util/SocketClient.cpp: Auto merged ndb/src/common/util/random.c: Auto merged ndb/src/common/util/socket_io.cpp: Auto merged ndb/src/cw/cpcd/APIService.cpp: Auto merged ndb/src/cw/cpcd/main.cpp: Auto merged ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp: Auto merged ndb/src/kernel/blocks/dbdict/Dbdict.cpp: Auto merged ndb/src/kernel/blocks/dbdict/Dbdict.hpp: Auto merged ndb/src/kernel/blocks/dbdih/Dbdih.hpp: Auto merged ndb/src/kernel/blocks/dblqh/Dblqh.hpp: Auto merged ndb/src/kernel/blocks/dblqh/DblqhMain.cpp: Auto merged ndb/src/kernel/blocks/dbtc/Dbtc.hpp: Auto merged ndb/src/kernel/blocks/dbtup/Dbtup.hpp: Auto merged ndb/src/kernel/blocks/dbtup/DbtupScan.cpp: Auto merged ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp: Auto merged ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp: Auto merged ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp: Auto merged ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp: Auto merged ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp: Auto merged ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp: Auto merged ndb/src/kernel/blocks/qmgr/Qmgr.hpp: Auto merged ndb/src/kernel/blocks/qmgr/QmgrMain.cpp: Auto merged ndb/src/kernel/blocks/suma/Suma.cpp: Auto merged ndb/src/kernel/blocks/suma/Suma.hpp: Auto merged ndb/src/kernel/vm/MetaData.hpp: Auto merged ndb/src/mgmapi/LocalConfig.cpp: Auto merged ndb/src/mgmapi/mgmapi.cpp: Auto merged ndb/src/mgmclient/CommandInterpreter.cpp: Auto merged ndb/src/mgmsrv/ConfigInfo.cpp: Auto merged ndb/src/mgmsrv/ConfigInfo.hpp: Auto merged ndb/src/mgmsrv/InitConfigFileParser.cpp: Auto merged ndb/src/mgmsrv/MgmtSrvr.cpp: Auto merged ndb/src/mgmsrv/MgmtSrvr.hpp: Auto merged ndb/src/mgmsrv/Services.cpp: Auto merged ndb/src/mgmsrv/main.cpp: Auto merged ndb/src/ndbapi/ClusterMgr.hpp: Auto merged ndb/src/ndbapi/Ndb.cpp: Auto merged ndb/src/ndbapi/NdbBlob.cpp: Auto merged ndb/src/ndbapi/NdbDictionaryImpl.cpp: Auto merged ndb/src/ndbapi/NdbIndexOperation.cpp: Auto merged ndb/src/ndbapi/NdbOperationDefine.cpp: Auto merged ndb/src/ndbapi/NdbOperationExec.cpp: Auto merged ndb/src/ndbapi/NdbOperationSearch.cpp: Auto merged ndb/src/ndbapi/NdbScanFilter.cpp: Auto merged ndb/src/ndbapi/NdbScanOperation.cpp: Auto merged ndb/src/ndbapi/SignalSender.cpp: Auto merged ndb/src/ndbapi/ndb_cluster_connection.cpp: Auto merged ndb/tools/delete_all.cpp: Auto merged ndb/tools/desc.cpp: Auto merged ndb/tools/drop_index.cpp: Auto merged ndb/tools/drop_tab.cpp: Auto merged ndb/tools/listTables.cpp: Auto merged ndb/tools/ndb_config.cpp: Auto merged ndb/tools/restore/Restore.hpp: Auto merged ndb/tools/restore/consumer.hpp: Auto merged ndb/tools/restore/restore_main.cpp: Auto merged ndb/tools/select_all.cpp: Auto merged ndb/tools/select_count.cpp: Auto merged server-tools/instance-manager/commands.h: Auto merged server-tools/instance-manager/guardian.cc: Auto merged server-tools/instance-manager/instance_options.cc: Auto merged server-tools/instance-manager/mysql_connection.cc: Auto merged server-tools/instance-manager/options.cc: Auto merged server-tools/instance-manager/options.h: Auto merged server-tools/instance-manager/parse.cc: Auto merged server-tools/instance-manager/user_map.cc: Auto merged server-tools/instance-manager/user_map.h: Auto merged sql/field.cc: Auto merged sql/field.h: Auto merged sql/filesort.cc: Auto merged sql/ha_archive.cc: Auto merged sql/ha_archive.h: Auto merged sql/ha_federated.cc: Auto merged sql/ha_heap.cc: Auto merged sql/ha_myisam.cc: Auto merged sql/ha_myisammrg.cc: Auto merged sql/ha_ndbcluster.cc: Auto merged sql/handler.cc: Auto merged sql/item.cc: Auto merged sql/item.h: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_cmpfunc.h: Auto merged sql/item_func.cc: Auto merged sql/item_geofunc.cc: Auto merged sql/item_row.h: Auto merged sql/item_strfunc.cc: Auto merged sql/item_subselect.cc: Auto merged sql/item_subselect.h: Auto merged sql/item_sum.cc: Auto merged sql/item_timefunc.cc: Auto merged sql/log.cc: Auto merged sql/log_event.cc: Auto merged sql/log_event.h: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/net_serv.cc: Auto merged sql/opt_range.cc: Auto merged sql/opt_range.h: Auto merged sql/password.c: Auto merged sql/protocol.cc: Auto merged sql/repl_failsafe.cc: Auto merged sql/set_var.cc: Auto merged sql/set_var.h: Auto merged sql/slave.cc: Auto merged sql/sp.cc: Auto merged sql/sp_head.cc: Auto merged sql/sp_head.h: Auto merged sql/spatial.cc: Auto merged sql/spatial.h: Auto merged sql/sql_cache.h: Auto merged sql/sql_class.cc: Auto merged sql/sql_derived.cc: Auto merged sql/sql_insert.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_load.cc: Auto merged sql/sql_prepare.cc: Auto merged sql-common/client.c: Auto merged sql-common/my_time.c: Auto merged sql/sql_select.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_string.cc: Auto merged sql/sql_string.h: Auto merged sql/sql_table.cc: Auto merged sql/sql_trigger.cc: Auto merged sql/sql_trigger.h: Auto merged sql/sql_union.cc: Auto merged sql/sql_update.cc: Auto merged sql/sql_view.cc: Auto merged sql/sql_yacc.yy: Auto merged sql/table.cc: Auto merged sql/tztime.cc: Auto merged sql/unireg.cc: Auto merged strings/ctype-bin.c: Auto merged strings/ctype-cp932.c: Auto merged strings/ctype-eucjpms.c: Auto merged strings/ctype-mb.c: Auto merged strings/ctype-simple.c: Auto merged strings/ctype-sjis.c: Auto merged strings/ctype-uca.c: Auto merged strings/ctype-ujis.c: Auto merged strings/ctype-utf8.c: Auto merged strings/decimal.c: Auto merged strings/my_vsnprintf.c: Auto merged tests/mysql_client_test.c: Auto merged mysql-test/t/mysqlbinlog.test: Manual merge sql/sql_class.h: Manual merge sql/sql_parse.cc: Manual merge
432 lines
11 KiB
C++
432 lines
11 KiB
C++
/* Copyright (C) 2004 MySQL AB
|
|
|
|
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 */
|
|
|
|
|
|
#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
|
|
#pragma implementation
|
|
#endif
|
|
|
|
#include "guardian.h"
|
|
|
|
#include "instance_map.h"
|
|
#include "instance.h"
|
|
#include "mysql_manager_error.h"
|
|
#include "log.h"
|
|
#include "portability.h"
|
|
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <signal.h>
|
|
|
|
|
|
|
|
pthread_handler_t guardian(void *arg)
|
|
{
|
|
Guardian_thread *guardian_thread= (Guardian_thread *) arg;
|
|
guardian_thread->run();
|
|
return 0;
|
|
}
|
|
|
|
Guardian_thread::Guardian_thread(Thread_registry &thread_registry_arg,
|
|
Instance_map *instance_map_arg,
|
|
uint monitoring_interval_arg) :
|
|
Guardian_thread_args(thread_registry_arg, instance_map_arg,
|
|
monitoring_interval_arg),
|
|
thread_info(pthread_self()), guarded_instances(0)
|
|
{
|
|
pthread_mutex_init(&LOCK_guardian, 0);
|
|
pthread_cond_init(&COND_guardian, 0);
|
|
shutdown_requested= FALSE;
|
|
stopped= FALSE;
|
|
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
|
|
}
|
|
|
|
|
|
Guardian_thread::~Guardian_thread()
|
|
{
|
|
/* delay guardian destruction to the moment when no one needs it */
|
|
pthread_mutex_lock(&LOCK_guardian);
|
|
free_root(&alloc, MYF(0));
|
|
pthread_mutex_unlock(&LOCK_guardian);
|
|
pthread_mutex_destroy(&LOCK_guardian);
|
|
pthread_cond_destroy(&COND_guardian);
|
|
}
|
|
|
|
|
|
void Guardian_thread::request_shutdown()
|
|
{
|
|
pthread_mutex_lock(&LOCK_guardian);
|
|
/* stop instances or just clean up Guardian repository */
|
|
stop_instances();
|
|
shutdown_requested= TRUE;
|
|
pthread_mutex_unlock(&LOCK_guardian);
|
|
}
|
|
|
|
|
|
void Guardian_thread::process_instance(Instance *instance,
|
|
GUARD_NODE *current_node,
|
|
LIST **guarded_instances_arg,
|
|
LIST *node)
|
|
{
|
|
uint waitchild= (uint) Instance::DEFAULT_SHUTDOWN_DELAY;
|
|
/* The amount of times, Guardian attempts to restart an instance */
|
|
int restart_retry= 100;
|
|
time_t current_time= time(NULL);
|
|
|
|
if (current_node->state == STOPPING)
|
|
{
|
|
/* this brach is executed during shutdown */
|
|
if (instance->options.shutdown_delay_val)
|
|
waitchild= instance->options.shutdown_delay_val;
|
|
|
|
/* this returns true if and only if an instance was stopped for sure */
|
|
if (instance->is_crashed())
|
|
*guarded_instances_arg= list_delete(*guarded_instances_arg, node);
|
|
else if ( (uint) (current_time - current_node->last_checked) > waitchild)
|
|
{
|
|
instance->kill_instance(SIGKILL);
|
|
/*
|
|
Later we do node= node->next. This is ok, as we are only removing
|
|
the node from the list. The pointer to the next one is still valid.
|
|
*/
|
|
*guarded_instances_arg= list_delete(*guarded_instances_arg, node);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (instance->is_running())
|
|
{
|
|
/* The instance can be contacted on it's port */
|
|
|
|
/* If STARTING also check that pidfile has been created */
|
|
if (current_node->state == STARTING &&
|
|
current_node->instance->options.get_pid() == 0)
|
|
{
|
|
/* Pid file not created yet, don't go to STARTED state yet */
|
|
}
|
|
else if (current_node->state != STARTED)
|
|
{
|
|
/* clear status fields */
|
|
log_info("guardian: instance '%s' is running, set state to STARTED.",
|
|
(const char *) instance->options.instance_name);
|
|
current_node->restart_counter= 0;
|
|
current_node->crash_moment= 0;
|
|
current_node->state= STARTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (current_node->state) {
|
|
case NOT_STARTED:
|
|
log_info("guardian: starting instance '%s'...",
|
|
(const char *) instance->options.instance_name);
|
|
|
|
/* NOTE, set state to STARTING _before_ start() is called */
|
|
current_node->state= STARTING;
|
|
instance->start();
|
|
current_node->last_checked= current_time;
|
|
break;
|
|
case STARTED: /* fallthrough */
|
|
case STARTING: /* let the instance start or crash */
|
|
if (instance->is_crashed())
|
|
{
|
|
current_node->crash_moment= current_time;
|
|
current_node->last_checked= current_time;
|
|
current_node->state= JUST_CRASHED;
|
|
/* fallthrough -- restart an instance immediately */
|
|
}
|
|
else
|
|
break;
|
|
case JUST_CRASHED:
|
|
if (current_time - current_node->crash_moment <= 2)
|
|
{
|
|
if (instance->is_crashed())
|
|
{
|
|
instance->start();
|
|
log_info("guardian: starting instance '%s'...",
|
|
(const char *) instance->options.instance_name);
|
|
}
|
|
}
|
|
else
|
|
current_node->state= CRASHED;
|
|
break;
|
|
case CRASHED: /* just regular restarts */
|
|
if (current_time - current_node->last_checked >
|
|
monitoring_interval)
|
|
{
|
|
if ((current_node->restart_counter < restart_retry))
|
|
{
|
|
if (instance->is_crashed())
|
|
{
|
|
instance->start();
|
|
current_node->last_checked= current_time;
|
|
current_node->restart_counter++;
|
|
log_info("guardian: restarting instance '%s'...",
|
|
(const char *) instance->options.instance_name);
|
|
}
|
|
}
|
|
else
|
|
current_node->state= CRASHED_AND_ABANDONED;
|
|
}
|
|
break;
|
|
case CRASHED_AND_ABANDONED:
|
|
break; /* do nothing */
|
|
default:
|
|
DBUG_ASSERT(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
Run guardian thread
|
|
|
|
SYNOPSYS
|
|
run()
|
|
|
|
DESCRIPTION
|
|
|
|
Check for all guarded instances and restart them if needed. If everything
|
|
is fine go and sleep for some time.
|
|
*/
|
|
|
|
void Guardian_thread::run()
|
|
{
|
|
Instance *instance;
|
|
LIST *node;
|
|
struct timespec timeout;
|
|
|
|
thread_registry.register_thread(&thread_info);
|
|
|
|
my_thread_init();
|
|
pthread_mutex_lock(&LOCK_guardian);
|
|
|
|
/* loop, until all instances were shut down at the end */
|
|
while (!(shutdown_requested && (guarded_instances == NULL)))
|
|
{
|
|
node= guarded_instances;
|
|
|
|
while (node != NULL)
|
|
{
|
|
GUARD_NODE *current_node= (GUARD_NODE *) node->data;
|
|
instance= ((GUARD_NODE *) node->data)->instance;
|
|
process_instance(instance, current_node, &guarded_instances, node);
|
|
|
|
node= node->next;
|
|
}
|
|
set_timespec(timeout, monitoring_interval);
|
|
|
|
/* check the loop predicate before sleeping */
|
|
if (!(shutdown_requested && (!(guarded_instances))))
|
|
thread_registry.cond_timedwait(&thread_info, &COND_guardian,
|
|
&LOCK_guardian, &timeout);
|
|
}
|
|
|
|
stopped= TRUE;
|
|
pthread_mutex_unlock(&LOCK_guardian);
|
|
/* now, when the Guardian is stopped we can stop the IM */
|
|
thread_registry.unregister_thread(&thread_info);
|
|
thread_registry.request_shutdown();
|
|
my_thread_end();
|
|
}
|
|
|
|
|
|
int Guardian_thread::is_stopped()
|
|
{
|
|
int var;
|
|
pthread_mutex_lock(&LOCK_guardian);
|
|
var= stopped;
|
|
pthread_mutex_unlock(&LOCK_guardian);
|
|
return var;
|
|
}
|
|
|
|
|
|
/*
|
|
Initialize the list of guarded instances: loop through the Instance_map and
|
|
add all of the instances, which don't have 'nonguarded' option specified.
|
|
|
|
SYNOPSYS
|
|
Guardian_thread::init()
|
|
|
|
NOTE: One should always lock guardian before calling this routine.
|
|
|
|
RETURN
|
|
0 - ok
|
|
1 - error occured
|
|
*/
|
|
|
|
int Guardian_thread::init()
|
|
{
|
|
Instance *instance;
|
|
Instance_map::Iterator iterator(instance_map);
|
|
|
|
/* clear the list of guarded instances */
|
|
free_root(&alloc, MYF(0));
|
|
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
|
|
guarded_instances= NULL;
|
|
|
|
while ((instance= iterator.next()))
|
|
{
|
|
if (!(instance->options.nonguarded))
|
|
if (guard(instance, TRUE)) /* do not lock guardian */
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
Add instance to the Guardian list
|
|
|
|
SYNOPSYS
|
|
guard()
|
|
instance the instance to be guarded
|
|
nolock whether we prefer do not lock Guardian here,
|
|
but use external locking instead
|
|
|
|
DESCRIPTION
|
|
|
|
The instance is added to the guarded instances list. Usually guard() is
|
|
called after we start an instance.
|
|
|
|
RETURN
|
|
0 - ok
|
|
1 - error occured
|
|
*/
|
|
|
|
int Guardian_thread::guard(Instance *instance, bool nolock)
|
|
{
|
|
LIST *node;
|
|
GUARD_NODE *content;
|
|
|
|
node= (LIST *) alloc_root(&alloc, sizeof(LIST));
|
|
content= (GUARD_NODE *) alloc_root(&alloc, sizeof(GUARD_NODE));
|
|
|
|
if ((!(node)) || (!(content)))
|
|
return 1;
|
|
/* we store the pointers to instances from the instance_map's MEM_ROOT */
|
|
content->instance= instance;
|
|
content->restart_counter= 0;
|
|
content->crash_moment= 0;
|
|
content->state= NOT_STARTED;
|
|
node->data= (void*) content;
|
|
|
|
if (nolock)
|
|
guarded_instances= list_add(guarded_instances, node);
|
|
else
|
|
{
|
|
pthread_mutex_lock(&LOCK_guardian);
|
|
guarded_instances= list_add(guarded_instances, node);
|
|
pthread_mutex_unlock(&LOCK_guardian);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
TODO: perhaps it would make sense to create a pool of the LIST nodeents
|
|
and give them upon request. Now we are loosing a bit of memory when
|
|
guarded instance was stopped and then restarted (since we cannot free just
|
|
a piece of the MEM_ROOT).
|
|
*/
|
|
|
|
int Guardian_thread::stop_guard(Instance *instance)
|
|
{
|
|
LIST *node;
|
|
|
|
pthread_mutex_lock(&LOCK_guardian);
|
|
node= guarded_instances;
|
|
|
|
while (node != NULL)
|
|
{
|
|
/*
|
|
We compare only pointers, as we always use pointers from the
|
|
instance_map's MEM_ROOT.
|
|
*/
|
|
if (((GUARD_NODE *) node->data)->instance == instance)
|
|
{
|
|
guarded_instances= list_delete(guarded_instances, node);
|
|
pthread_mutex_unlock(&LOCK_guardian);
|
|
return 0;
|
|
}
|
|
else
|
|
node= node->next;
|
|
}
|
|
pthread_mutex_unlock(&LOCK_guardian);
|
|
/* if there is nothing to delete it is also fine */
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
An internal method which is called at shutdown to unregister instances and
|
|
attempt to stop them if requested.
|
|
|
|
SYNOPSYS
|
|
stop_instances()
|
|
|
|
DESCRIPTION
|
|
Loops through the guarded_instances list and prepares them for shutdown.
|
|
For each instance we issue a stop command and change the state
|
|
accordingly.
|
|
|
|
NOTE
|
|
Guardian object should be locked by the calling function.
|
|
|
|
RETURN
|
|
0 - ok
|
|
1 - error occured
|
|
*/
|
|
|
|
int Guardian_thread::stop_instances()
|
|
{
|
|
LIST *node;
|
|
node= guarded_instances;
|
|
while (node != NULL)
|
|
{
|
|
GUARD_NODE *current_node= (GUARD_NODE *) node->data;
|
|
/*
|
|
If instance is running or was running (and now probably hanging),
|
|
request stop.
|
|
*/
|
|
if (current_node->instance->is_running() ||
|
|
(current_node->state == STARTED))
|
|
{
|
|
current_node->state= STOPPING;
|
|
current_node->last_checked= time(NULL);
|
|
}
|
|
else
|
|
/* otherwise remove it from the list */
|
|
guarded_instances= list_delete(guarded_instances, node);
|
|
/* But try to kill it anyway. Just in case */
|
|
current_node->instance->kill_instance(SIGTERM);
|
|
node= node->next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
void Guardian_thread::lock()
|
|
{
|
|
pthread_mutex_lock(&LOCK_guardian);
|
|
}
|
|
|
|
|
|
void Guardian_thread::unlock()
|
|
{
|
|
pthread_mutex_unlock(&LOCK_guardian);
|
|
}
|