diff options
author | Sinisa@sinisa.nasamreza.org <> | 2004-03-11 22:27:17 +0200 |
---|---|---|
committer | Sinisa@sinisa.nasamreza.org <> | 2004-03-11 22:27:17 +0200 |
commit | 37817f60cc3c0b47eaffe8f5e16f713c81354ef9 (patch) | |
tree | ae721a5579bd59c34fd338e2766c936f952314e9 /sql | |
parent | a86753b00e27409d1ec1223e20d872f1b8fa1848 (diff) | |
parent | 2bf78563f7a87cbeac8201f06983e5caab5b0cc6 (diff) | |
download | mariadb-git-37817f60cc3c0b47eaffe8f5e16f713c81354ef9.tar.gz |
Merge sinisa@bk-internal.mysql.com:/home/bk/mysql-4.0
into sinisa.nasamreza.org:/mnt/work/mysql-4.0
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_func.cc | 2 | ||||
-rw-r--r-- | sql/log_event.cc | 159 | ||||
-rw-r--r-- | sql/mysql_priv.h | 1 | ||||
-rw-r--r-- | sql/repl_failsafe.cc | 8 | ||||
-rw-r--r-- | sql/set_var.cc | 8 | ||||
-rw-r--r-- | sql/slave.cc | 28 | ||||
-rw-r--r-- | sql/slave.h | 36 | ||||
-rw-r--r-- | sql/sql_parse.cc | 71 | ||||
-rw-r--r-- | sql/sql_show.cc | 4 |
9 files changed, 183 insertions, 134 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc index 656dff63609..ab96915e746 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1543,13 +1543,11 @@ longlong Item_master_pos_wait::val_int() } longlong pos = args[1]->val_int(); longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ; - LOCK_ACTIVE_MI; if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2) { null_value = 1; event_count=0; } - UNLOCK_ACTIVE_MI; return event_count; } diff --git a/sql/log_event.cc b/sql/log_event.cc index d2957165e77..a484123b4c7 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -53,6 +53,14 @@ static void pretty_print_str(FILE* file, char* str, int len) #ifndef MYSQL_CLIENT +static void clear_all_errors(THD *thd, struct st_relay_log_info *rli) +{ + thd->query_error = 0; + thd->clear_error(); + *rli->last_slave_error = 0; + rli->last_slave_errno = 0; +} + inline int ignored_error_code(int err_code) { return ((err_code == ER_SLAVE_IGNORED_TABLE) || @@ -1803,8 +1811,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) #else rli->future_group_master_log_pos= log_pos; #endif - thd->query_error= 0; // clear error - thd->clear_error(); + clear_all_errors(thd, rli); if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { @@ -1817,84 +1824,93 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->slave_proxy_id = thread_id; // for temp tables - /* - Sanity check to make sure the master did not get a really bad - error on the query. - */ - if (ignored_error_code((expected_error = error_code)) || - !check_expected_error(thd,rli,expected_error)) - { - mysql_log.write(thd,COM_QUERY,"%s",thd->query); - DBUG_PRINT("query",("%s",thd->query)); + mysql_log.write(thd,COM_QUERY,"%s",thd->query); + DBUG_PRINT("query",("%s",thd->query)); + if (ignored_error_code(expected_error = error_code) || + !check_expected_error(thd,rli,expected_error)) mysql_parse(thd, thd->query, q_len); - - /* - Set a flag if we are inside an transaction so that we can restart - the transaction from the start if we are killed - - This will only be done if we are supporting transactional tables - in the slave. - */ - if (!strcmp(thd->query,"BEGIN")) - rli->inside_transaction= opt_using_transactions; - else if (!(strcmp(thd->query,"COMMIT") && strcmp(thd->query,"ROLLBACK"))) - rli->inside_transaction=0; - + else + { /* - If we expected a non-zero error code, and we don't get the same error - code, and none of them should be ignored. + The query got a really bad error on the master (thread killed etc), + which could be inconsistent. Parse it to test the table names: if the + replicate-*-do|ignore-table rules say "this query must be ignored" then + we exit gracefully; otherwise we warn about the bad error and tell DBA + to check/fix it. */ - if ((expected_error != (actual_error = thd->net.last_errno)) && - expected_error && - !ignored_error_code(actual_error) && - !ignored_error_code(expected_error)) + if (mysql_test_parse_for_slave(thd, thd->query, q_len)) + /* Can ignore query */ + clear_all_errors(thd, rli); + else { - slave_print_error(rli, 0, - "\ + slave_print_error(rli,expected_error, + "query '%s' partially completed on the master \ +(error on master: %d) \ +and was aborted. There is a chance that your master is inconsistent at this \ +point. If you are sure that your master is ok, run this query manually on the\ + slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;\ + START SLAVE; .", thd->query, expected_error); + thd->query_error= 1; + } + goto end; + } + + /* + Set a flag if we are inside an transaction so that we can restart + the transaction from the start if we are killed + + This will only be done if we are supporting transactional tables + in the slave. + */ + if (!strcmp(thd->query,"BEGIN")) + rli->inside_transaction= opt_using_transactions; + else if (!(strcmp(thd->query,"COMMIT") && strcmp(thd->query,"ROLLBACK"))) + rli->inside_transaction=0; + + /* + If we expected a non-zero error code, and we don't get the same error + code, and none of them should be ignored. + */ + if ((expected_error != (actual_error = thd->net.last_errno)) && + expected_error && + !ignored_error_code(actual_error) && + !ignored_error_code(expected_error)) + { + slave_print_error(rli, 0, + "\ Query '%s' caused different errors on master and slave. \ Error on master: '%s' (%d), Error on slave: '%s' (%d). \ Default database: '%s'", - query, - ER_SAFE(expected_error), - expected_error, - actual_error ? thd->net.last_error: "no error", - actual_error, - print_slave_db_safe(db)); - thd->query_error= 1; - } - /* - If we get the same error code as expected, or they should be ignored. - */ - else if (expected_error == actual_error || - ignored_error_code(actual_error)) - { - thd->query_error = 0; - thd->clear_error(); - *rli->last_slave_error = 0; - rli->last_slave_errno = 0; - } - /* - Other cases: mostly we expected no error and get one. - */ - else if (thd->query_error || thd->fatal_error) - { - slave_print_error(rli,actual_error, - "Error '%s' on query '%s'. Default database: '%s'", - (actual_error ? thd->net.last_error : - "unexpected success or fatal error"), - query, - print_slave_db_safe(db)); - thd->query_error= 1; - } - } - /* - End of sanity check. If the test was wrong, the query got a really bad - error on the master, which could be inconsistent, abort and tell DBA to - check/fix it. check_expected_error() already printed the message to - stderr and rli, and set thd->query_error to 1. + query, + ER_SAFE(expected_error), + expected_error, + actual_error ? thd->net.last_error: "no error", + actual_error, + print_slave_db_safe(db)); + thd->query_error= 1; + } + /* + If we get the same error code as expected, or they should be ignored. + */ + else if (expected_error == actual_error || + ignored_error_code(actual_error)) + clear_all_errors(thd, rli); + /* + Other cases: mostly we expected no error and get one. */ + else if (thd->query_error || thd->fatal_error) + { + slave_print_error(rli,actual_error, + "Error '%s' on query '%s'. Default database: '%s'", + (actual_error ? thd->net.last_error : + "unexpected success or fatal error"), + query, + print_slave_db_safe(db)); + thd->query_error= 1; + } } /* End of if (db_ok(... */ +end: VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->db= 0; // prevent db from being freed thd->query= 0; // just to be sure @@ -1939,8 +1955,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, thd->db= (char*) rewrite_db(db); DBUG_ASSERT(thd->query == 0); thd->query = 0; // Should not be needed - thd->query_error = 0; - thd->clear_error(); + clear_all_errors(thd, rli); if (!use_rli_only_for_errors) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 091e51629f0..3267b42effc 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -353,6 +353,7 @@ int quick_rm_table(enum db_type base,const char *db, bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); bool mysql_change_db(THD *thd,const char *name); void mysql_parse(THD *thd,char *inBuf,uint length); +bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length); void mysql_init_select(LEX *lex); bool mysql_new_select(LEX *lex); void mysql_init_multi_delete(LEX *lex); diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 56789a01bf4..e687b227946 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -750,7 +750,7 @@ int load_master_data(THD* thd) We do not want anyone messing with the slave at all for the entire duration of the data load. */ - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); lock_slave_threads(active_mi); init_thread_mask(&restart_thread_mask,active_mi,0 /*not inverse*/); if (restart_thread_mask && @@ -759,7 +759,7 @@ int load_master_data(THD* thd) { send_error(&thd->net,error); unlock_slave_threads(active_mi); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); return 1; } @@ -913,7 +913,7 @@ int load_master_data(THD* thd) { send_error(&thd->net, 0, "Failed purging old relay logs"); unlock_slave_threads(active_mi); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); return 1; } pthread_mutex_lock(&active_mi->rli.data_lock); @@ -934,7 +934,7 @@ int load_master_data(THD* thd) err: unlock_slave_threads(active_mi); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); thd->proc_info = 0; mc_mysql_close(&mysql); // safe to call since we always do mc_mysql_init() diff --git a/sql/set_var.cc b/sql/set_var.cc index 51ea6047794..71c0865dd91 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1273,7 +1273,7 @@ byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type) bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) { int result= 0; - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); pthread_mutex_lock(&active_mi->rli.run_lock); if (active_mi->rli.slave_running) { @@ -1281,14 +1281,14 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) result=1; } pthread_mutex_unlock(&active_mi->rli.run_lock); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); return result; } bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) { - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); pthread_mutex_lock(&active_mi->rli.run_lock); /* The following test should normally never be true as we test this @@ -1302,7 +1302,7 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) pthread_mutex_unlock(&active_mi->rli.data_lock); } pthread_mutex_unlock(&active_mi->rli.run_lock); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); return 0; } diff --git a/sql/slave.cc b/sql/slave.cc index 84f4ff4f3e0..d6dda473be0 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -34,7 +34,6 @@ typedef bool (*CHECK_KILLED_FUNC)(THD*,void*); volatile bool slave_sql_running = 0, slave_io_running = 0; char* slave_load_tmpdir = 0; MASTER_INFO *active_mi; -volatile int active_mi_in_use = 0; HASH replicate_do_table, replicate_ignore_table; DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table; bool do_table_inited = 0, ignore_table_inited = 0; @@ -114,8 +113,12 @@ int init_slave() { DBUG_ENTER("init_slave"); - /* This is called when mysqld starts */ - + /* + This is called when mysqld starts. Before client connections are + accepted. However bootstrap may conflict with us if it does START SLAVE. + So it's safer to take the lock. + */ + pthread_mutex_lock(&LOCK_active_mi); /* TODO: re-write this to interate through the list of files for multi-master @@ -160,9 +163,11 @@ int init_slave() goto err; } } + pthread_mutex_unlock(&LOCK_active_mi); DBUG_RETURN(0); err: + pthread_mutex_unlock(&LOCK_active_mi); DBUG_RETURN(1); } @@ -806,7 +811,14 @@ static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/) void end_slave() { - /* This is called when the server terminates, in close_connections(). */ + /* + This is called when the server terminates, in close_connections(). + It terminates slave threads. However, some CHANGE MASTER etc may still be + running presently. If a START SLAVE was in progress, the mutex lock below + will make us wait until slave threads have started, and START SLAVE + returns, then we terminate them here. + */ + pthread_mutex_lock(&LOCK_active_mi); if (active_mi) { /* @@ -827,6 +839,7 @@ void end_slave() delete active_mi; active_mi= 0; } + pthread_mutex_unlock(&LOCK_active_mi); } @@ -2237,13 +2250,6 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error) case ER_NET_ERROR_ON_WRITE: case ER_SERVER_SHUTDOWN: case ER_NEW_ABORTING_CONNECTION: - slave_print_error(rli,expected_error, - "query '%s' partially completed on the master \ -and was aborted. There is a chance that your master is inconsistent at this \ -point. If you are sure that your master is ok, run this query manually on the\ - slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;\ - SLAVE START; .", thd->query); - thd->query_error= 1; return 1; default: return 0; diff --git a/sql/slave.h b/sql/slave.h index 9877582d094..4a6389e9f87 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -27,12 +27,19 @@ /* MUTEXES in replication: - LOCK_active_mi: this is meant for multimaster, when we can switch from a - master to another. It protects active_mi. We don't care of it for the moment, - as active_mi never moves (it's created at startup and deleted at shutdown, and - not changed: it always points to the same MASTER_INFO struct), because we - don't have multimaster. So for the moment, mi does not move, and mi->rli does - not either. + LOCK_active_mi: [note: this was originally meant for multimaster, to switch + from a master to another, to protect active_mi] It is used to SERIALIZE ALL + administrative commands of replication: START SLAVE, STOP SLAVE, CHANGE + MASTER, RESET SLAVE, end_slave() (when mysqld stops) [init_slave() does not + need it it's called early]. Any of these commands holds the mutex from the + start till the end. This thus protects us against a handful of deadlocks + (consider start_slave_thread() which, when starting the I/O thread, releases + mi->run_lock, keeps rli->run_lock, and tries to re-acquire mi->run_lock). + + Currently active_mi never moves (it's created at startup and deleted at + shutdown, and not changed: it always points to the same MASTER_INFO struct), + because we don't have multimaster. So for the moment, mi does not move, and + mi->rli does not either. In MASTER_INFO: run_lock, data_lock run_lock protects all information about the run state: slave_running, and the @@ -43,6 +50,9 @@ In RELAY_LOG_INFO: run_lock, data_lock see MASTER_INFO + Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you + must acquire LOCK_active_mi first. + In MYSQL_LOG: LOCK_log, LOCK_index of the binlog and the relay log LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog (so that you have to update the .index file). @@ -65,19 +75,6 @@ enum enum_binlog_formats { BINLOG_FORMAT_323_GEQ_57 }; /* - TODO: this needs to be redone, but for now it does not matter since - we do not have multi-master yet. -*/ - -#define LOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \ - ++active_mi_in_use; \ - pthread_mutex_unlock(&LOCK_active_mi);} - -#define UNLOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \ - --active_mi_in_use; \ - pthread_mutex_unlock(&LOCK_active_mi); } - -/* st_relay_log_info contains information on the current relay log and relay log offset, and master log name and log sequence corresponding to the last update. Additionally, misc information specific to the SQL thread is @@ -441,7 +438,6 @@ extern "C" pthread_handler_decl(handle_slave_io,arg); extern "C" pthread_handler_decl(handle_slave_sql,arg); extern bool volatile abort_loop; extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */ -extern volatile int active_mi_in_use; extern LIST master_list; extern HASH replicate_do_table, replicate_ignore_table; extern DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index bc69f7136ad..5b1487aa313 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -65,6 +65,7 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result, bool skip_first); static bool check_one_table_access(THD *thd, ulong want_access, TABLE_LIST *table, bool no_errors); +static inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables); const char *any_db="*any*"; // Special symbol for check_access @@ -1332,9 +1333,7 @@ mysql_execute_command(void) Skip if we are in the slave thread, some table rules have been given and the table list says the query should not be replicated */ - if (table_rules_on && tables && !tables_ok(thd,tables) && - ((lex->sql_command != SQLCOM_DELETE_MULTI) || - !tables_ok(thd,(TABLE_LIST *)thd->lex.auxilliary_table_list.first))) + if (all_tables_not_ok(thd,tables)) { /* we warn the slave SQL thread */ my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); @@ -1519,9 +1518,9 @@ mysql_execute_command(void) { if (check_global_access(thd, SUPER_ACL)) goto error; - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); res = change_master(thd,active_mi); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); break; } case SQLCOM_SHOW_SLAVE_STAT: @@ -1529,9 +1528,9 @@ mysql_execute_command(void) /* Accept one of two privileges */ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) goto error; - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); res = show_master_info(thd,active_mi); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); break; } case SQLCOM_SHOW_MASTER_STAT: @@ -1581,7 +1580,7 @@ mysql_execute_command(void) if (error) goto error; } - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); /* fetch_master_table will send the error to the client on failure. Give error if the table already exists. @@ -1591,7 +1590,7 @@ mysql_execute_command(void) { send_ok(&thd->net); } - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); break; } #endif /* HAVE_REPLICATION */ @@ -1702,9 +1701,9 @@ mysql_execute_command(void) #ifdef HAVE_REPLICATION case SQLCOM_SLAVE_START: { - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); start_slave(thd,active_mi,1 /* net report*/); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); break; } case SQLCOM_SLAVE_STOP: @@ -1727,9 +1726,9 @@ mysql_execute_command(void) break; } { - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); stop_slave(thd,active_mi,1/* net report*/); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); break; } #endif /* HAVE_REPLICATION */ @@ -2968,9 +2967,18 @@ void mysql_init_multi_delete(LEX *lex) lex->select->table_list.save_and_clear(&lex->auxilliary_table_list); } +static inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables) +{ + return (table_rules_on && tables && !tables_ok(thd,tables) && + ((thd->lex.sql_command != SQLCOM_DELETE_MULTI) || + !tables_ok(thd,(TABLE_LIST *)thd->lex.auxilliary_table_list.first))); +} -void -mysql_parse(THD *thd,char *inBuf,uint length) +/* + When you modify mysql_parse(), you may need to mofify + mysql_test_parse_for_slave() in this same file. +*/ +void mysql_parse(THD *thd, char *inBuf, uint length) { DBUG_ENTER("mysql_parse"); @@ -3005,6 +3013,31 @@ mysql_parse(THD *thd,char *inBuf,uint length) DBUG_VOID_RETURN; } +/* + Usable by the replication SQL thread only: just parse a query to know if it + can be ignored because of replicate-*-table rules. + + RETURN VALUES + 0 cannot be ignored + 1 can be ignored +*/ + +bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) +{ + LEX *lex; + bool error= 0; + + mysql_init_query(thd); + lex= lex_start(thd, (uchar*) inBuf, length); + if (!yyparse() && ! thd->fatal_error && + all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) + error= 1; /* Ignore question */ + free_items(thd); /* Free strings used by items */ + lex_end(lex); + + return error; +} + /***************************************************************************** ** Store field definition for create @@ -3638,9 +3671,9 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables) mysql_update_log.new_file(1); mysql_bin_log.new_file(1); mysql_slow_log.new_file(1); - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); rotate_relay_log(active_mi); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); if (ha_flush_logs()) result=1; @@ -3685,7 +3718,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables) #endif if (options & REFRESH_SLAVE) { - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); if (reset_slave(thd, active_mi)) { result=1; @@ -3697,7 +3730,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables) */ error_already_sent=1; } - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); } if (options & REFRESH_USER_RESOURCES) reset_mqh(thd,(LEX_USER *) NULL); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3d727a33173..63f3afab128 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1270,11 +1270,11 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, #ifdef HAVE_REPLICATION case SHOW_SLAVE_RUNNING: { - LOCK_ACTIVE_MI; + pthread_mutex_lock(&LOCK_active_mi); net_store_data(&packet2, (active_mi->slave_running && active_mi->rli.slave_running) ? "ON" : "OFF"); - UNLOCK_ACTIVE_MI; + pthread_mutex_unlock(&LOCK_active_mi); break; } #endif |