Skip to content

Commit

Permalink
[YottaDB#215] Enhance DEFERRED_EXIT_HANDLING_CHECK macro to handle no…
Browse files Browse the repository at this point in the history
…t just deferred signals that terminate the process but also those that suspend the process (Ctrl-Z)

In the v63004/gtm8791 subtest, it was noticed that a Ctrl-Z was not handled
(i.e. the process was not suspended) when the test ran on slower systems.
Turns out it was because when the LKE> prompt was being displayed, interrupts
are deferred in the process and if a Ctrl-Z is done at that time, we set
the global variable "suspend_status" to DEFER_SUSPEND to record this fact
and continue but once the interrupts are enabled, we only do checks of deferred
exit handling signals, not of the suspend signal. This means the Ctrl-Z is
effectively ignored. At least until the next rel_crit/rel_lock happens in this
process since that is when the "suspend_status" global is checked again. This
is unfriendly so the DEFERRED_EXIT_HANDLING_CHECK macro (which is invoked every
time we come out of an interrupt deferred zone) is renamed as
DEFERRED_SIGNAL_HANDLING_CHECK and Ctrl-Z deferral is also checked as part of
this macro.
  • Loading branch information
nars1 committed Apr 27, 2018
1 parent 6a5f0b2 commit 79f26fa
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 24 deletions.
6 changes: 3 additions & 3 deletions sr_port/gtm_malloc_src.h
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ void *gtm_malloc(size_t size) /* Note renamed to gtm_malloc_dbg when included in
TRACE_MALLOC(retVal, size, smTn);
--gtmMallocDepth;
--fast_lock_count;
DEFERRED_EXIT_HANDLING_CHECK;
DEFERRED_SIGNAL_HANDLING_CHECK;
PTHREAD_MUTEX_UNLOCK_IF_NEEDED(was_holder); /* release exclusive thread lock if needed */
return retVal;
} else /* Storage mgmt has not been initialized */
Expand Down Expand Up @@ -1025,7 +1025,7 @@ void gtm_free(void *addr) /* Note renamed to gtm_free_dbg when included in gtm_m
gtm_free_dbg(addr);
}
# endif
DEFERRED_EXIT_HANDLING_CHECK;
DEFERRED_SIGNAL_HANDLING_CHECK;
}

/* When an out-of-storage type error is encountered, besides releasing our memory reserve, we also
Expand Down Expand Up @@ -1096,7 +1096,7 @@ void raise_gtmmemory_error(void) /* Note renamed to raise_gtmmemory_error_dbg wh
} else
--gtmMallocDepth;
--fast_lock_count;
DEFERRED_EXIT_HANDLING_CHECK;
DEFERRED_SIGNAL_HANDLING_CHECK;
was_holder = TRUE; /* caller (gtm_malloc/gtm_free) got the thread lock so release it before the rts_error */
PTHREAD_MUTEX_UNLOCK_IF_NEEDED(was_holder); /* release exclusive thread lock if needed */
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_MEMORY, 2, gtmMallocErrorSize, gtmMallocErrorCallerid,
Expand Down
28 changes: 21 additions & 7 deletions sr_port/have_crit.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
* Copyright (c) 2001-2017 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* Copyright (c) 2018 YottaDB LLC. and/or its subsidiaries. *
* All rights reserved. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
Expand All @@ -14,9 +17,8 @@
#define HAVE_CRIT_H_INCLUDED

#include <signal.h> /* needed for VSIG_ATOMIC_T */
#ifdef UNIX
#include <deferred_signal_handler.h>
#endif
#include "gtmsiginfo.h" /* for DEFER_SUSPEND */

/* states of CRIT passed as argument to have_crit() */
#define CRIT_HAVE_ANY_REG 0x00000001
Expand Down Expand Up @@ -112,8 +114,8 @@ GBLREF boolean_t deferred_timers_check_needed;
* deferred events, from timers or other interrupts, anymore. Ensure that forced_exit state does not regress by asserting that the
* current value is 0 or 1 before setting it to 2. Note that on UNIX forced_exit can progress to 2 only from 1, while on VMS it is
* possible to generic_exit_handler or dbcertify_exit_handler to change forced_exit from 0 to 2 directly. This design ensures that
* on VMS we will not invoke sys$exit from DEFERRED_EXIT_HANDLING_CHECK after we started exit processing; on UNIX process_exiting
* flag servs the same purpose (and is also checked by DEFERRED_EXIT_HANDLING_CHECK), so it is not necessary for either
* on VMS we will not invoke sys$exit from DEFERRED_SIGNAL_HANDLING_CHECK after we started exit processing; on UNIX process_exiting
* flag servs the same purpose (and is also checked by DEFERRED_SIGNAL_HANDLING_CHECK), so it is not necessary for either
* generic_signal_handler or dbcertify_signal_handler to set forced_exit to 2.
*/
#define SET_FORCED_EXIT_STATE_ALREADY_EXITING \
Expand All @@ -129,16 +131,17 @@ GBLREF boolean_t deferred_timers_check_needed;
forced_exit = 2; \
}

/* Macro to be used whenever we want to handle any signals that we deferred handling and exit in the process.
/* Macro to be used whenever we want to handle any signals that we deferred handling in the process.
* In VMS, we dont do any signal handling, only exit handling.
*/
#define DEFERRED_EXIT_HANDLING_CHECK \
#define DEFERRED_SIGNAL_HANDLING_CHECK \
{ \
char *rname; \
\
GBLREF int process_exiting; \
GBLREF VSIG_ATOMIC_T forced_exit; \
GBLREF volatile int4 gtmMallocDepth; \
GBLREF volatile int suspend_status; \
\
/* The forced_exit state of 2 indicates that the exit is already in progress, so we do not \
* need to process any deferred events. Note if threads are running, check if forced_exit is \
Expand All @@ -161,6 +164,16 @@ GBLREF boolean_t deferred_timers_check_needed;
if (!process_exiting && OK_TO_INTERRUPT) \
check_for_deferred_timers(); \
} \
/* Check if a Ctrl-Z signal handling was deferred and if it is safe to do so now */ \
if ((DEFER_SUSPEND == suspend_status) && OK_TO_INTERRUPT) \
{ /* Reset the global "suspend_status" before doing the "suspend" call as the \
* latter can call some other function which has a deferred zone and in turn \
* invokes DEFERRED_SIGNAL_HANDLING_CHECK at which point we do not want to \
* again do a nested suspend(SIGSTOP) processing. \
*/ \
suspend_status = NO_SUSPEND; \
suspend(SIGSTOP); \
} \
} \
}

Expand Down Expand Up @@ -217,9 +230,10 @@ GBLREF boolean_t multi_thread_in_use; /* TRUE => threads are in use. FALSE => n
assert(OLDSTATE == intrpt_ok_state); \
intrpt_ok_state = NEWSTATE; \
if (INTRPT_OK_TO_INTERRUPT == intrpt_ok_state) \
DEFERRED_EXIT_HANDLING_CHECK; /* check if signals were deferred in deferred zone */ \
DEFERRED_SIGNAL_HANDLING_CHECK; /* check if signals were deferred in deferred zone */ \
} \
}

#define OK_TO_SEND_MSG ((INTRPT_IN_X_TIME_FUNCTION != intrpt_ok_state) \
&& (INTRPT_IN_LOG_FUNCTION != intrpt_ok_state) \
&& (INTRPT_IN_FUNC_WITH_MALLOC != intrpt_ok_state) \
Expand Down
2 changes: 1 addition & 1 deletion sr_port/secshr_db_clnup.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ void secshr_db_clnup(enum secshr_db_state secshr_state)
jnlpool = save_jnlpool;
}
/* It is possible we are exiting while in the middle of a transaction (e.g. called through "deferred_signal_handler"
* in the DEFERRED_EXIT_HANDLING_CHECK macro). Since exit handling code can start new non-TP transactions
* in the DEFERRED_SIGNAL_HANDLING_CHECK macro). Since exit handling code can start new non-TP transactions
* (e.g. for statsdb rundown you need to kill ^%YGS node, for recording mprof stats you need to set a global node)
* clean up the effects of any in-progress transaction before the "t_begin" call happens.
*/
Expand Down
4 changes: 2 additions & 2 deletions sr_port/t_end.c
Original file line number Diff line number Diff line change
Expand Up @@ -1771,7 +1771,7 @@ trans_num t_end(srch_hist *hist1, srch_hist *hist2, trans_num ctn)
assert(!csa->now_crit || csa->hold_onto_crit);
assert(cdb_sc_normal == status);
REVERT; /* no need for t_ch to be invoked if any errors occur after this point */
DEFERRED_EXIT_HANDLING_CHECK; /* now that all crits are released, check if deferred signal/exit handling needs to be done */
DEFERRED_SIGNAL_HANDLING_CHECK; /* now that crits are released, check if deferred signal/exit handling needs to be done */
assert(update_trans);
if (REPL_ALLOWED(csa) && IS_DSE_IMAGE)
{
Expand Down Expand Up @@ -1849,7 +1849,7 @@ trans_num t_end(srch_hist *hist1, srch_hist *hist2, trans_num ctn)
* is if hold_onto_crit is set to TRUE in which case t_commit_cleanup honors it. Assert accordingly.
*/
assert(!csa->now_crit || !NEED_TO_RELEASE_CRIT(t_tries, status) || csa->hold_onto_crit);
DEFERRED_EXIT_HANDLING_CHECK; /* now that all crits are released, check if deferred signal/exit handling needs to be done */
DEFERRED_SIGNAL_HANDLING_CHECK; /* now that crits are released, check if deferred signal/exit handling needs to be done */
t_retry(status);
/* Note that even though cw_stagnate is used only in the final retry, it is possible we restart in the final retry
* (see "final_retry_ok" codes in cdb_sc_table.h) and so a CWS_RESET is necessary in that case. It is anyways a no-op
Expand Down
2 changes: 1 addition & 1 deletion sr_port/tp_tend.c
Original file line number Diff line number Diff line change
Expand Up @@ -1878,7 +1878,7 @@ boolean_t tp_tend()
}
skip_failed:
REVERT;
DEFERRED_EXIT_HANDLING_CHECK; /* now that all crits are released, check if deferred signal/exit handling needs to be done */
DEFERRED_SIGNAL_HANDLING_CHECK; /* now that crits are released, check if deferred signal/exit handling needs to be done */
if (cdb_sc_normal == status)
{
if (save_jnlpool != jnlpool)
Expand Down
7 changes: 5 additions & 2 deletions sr_unix/gtm_multi_thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
* Copyright (c) 2015 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* Copyright (c) 2018 YottaDB LLC. and/or its subsidiaries. *
* All rights reserved. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
Expand All @@ -20,7 +23,7 @@

#include "gtm_multi_thread.h"
#include "iosp.h" /* for SS_NORMAL */
#include "have_crit.h" /* for DEFERRED_EXIT_HANDLING_CHECK */
#include "have_crit.h" /* for DEFERRED_SIGNAL_HANDLING_CHECK */
#include "gtmimagename.h"
#ifdef DEBUG
#include "wbox_test_init.h"
Expand Down Expand Up @@ -175,7 +178,7 @@ int gtm_multi_thread(gtm_pthread_fnptr_t fnptr, int ntasks, int max_threads,
}
}
multi_thread_in_use = FALSE;
DEFERRED_EXIT_HANDLING_CHECK; /* Now that all threads have terminated, check for need of deferred signal/exit handling */
DEFERRED_SIGNAL_HANDLING_CHECK; /* Now that all threads have terminated, check for need of deferred signal/exit handling */
rc = pthread_attr_destroy(&attr); /* Free attribute */
if (rc)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8)
Expand Down
4 changes: 2 additions & 2 deletions sr_unix/op_fnfgncal.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,12 +613,12 @@ STATICFNDEF void op_fgnjavacal(mval *dst, mval *package, mval *extref, uint4 mas
#endif
save_mumps_status = mumps_status; /* Save mumps_status as a callin from external call may change it. */
save_in_ext_call = TREF(in_ext_call);
assert(INTRPT_OK_TO_INTERRUPT == intrpt_ok_state); /* Expected for DEFERRED_EXIT_HANDLING_CHECK below */
assert(INTRPT_OK_TO_INTERRUPT == intrpt_ok_state); /* Expected for DEFERRED_SIGNAL_HANDLING_CHECK below */
TREF(in_ext_call) = TRUE;
status = callg((callgfnptr)entry_ptr->fcn, param_list);
TREF(in_ext_call) = save_in_ext_call;
if (!save_in_ext_call)
DEFERRED_EXIT_HANDLING_CHECK; /* Check for deferred wcs_stale() timer */
DEFERRED_SIGNAL_HANDLING_CHECK; /* Check for deferred wcs_stale() timer */
mumps_status = save_mumps_status;
/* The first byte of the type description argument gets set to 0xFF in case error happened in JNI glue code,
* so check for that and act accordingly.
Expand Down
7 changes: 4 additions & 3 deletions sr_unix/rel_crit.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
* Copyright (c) 2001-2017 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* Copyright (c) 2018 YottaDB LLC. and/or its subsidiaries. *
* All rights reserved. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
Expand Down Expand Up @@ -81,7 +84,5 @@ void rel_crit(gd_region *reg)
} else
CRIT_TRACE(csa, crit_ops_nocrit);
/* Now that crit for THIS region is released, check if deferred signal/exit handling can be done and if so do it */
DEFERRED_EXIT_HANDLING_CHECK;
if ((DEFER_SUSPEND == suspend_status) && OK_TO_INTERRUPT)
suspend(SIGSTOP);
DEFERRED_SIGNAL_HANDLING_CHECK;
}
7 changes: 4 additions & 3 deletions sr_unix/rel_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
* Copyright (c) 2001-2017 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* Copyright (c) 2018 YottaDB LLC. and/or its subsidiaries. *
* All rights reserved. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
Expand Down Expand Up @@ -85,7 +88,5 @@ void rel_lock(gd_region *reg)
} else
CRIT_TRACE(csa, crit_ops_nocrit);
/* Now that crit for THIS region is released, check if deferred signal/exit handling can be done and if so do it */
DEFERRED_EXIT_HANDLING_CHECK;
if ((DEFER_SUSPEND == suspend_status) && OK_TO_INTERRUPT)
suspend(SIGSTOP);
DEFERRED_SIGNAL_HANDLING_CHECK;
}

0 comments on commit 79f26fa

Please sign in to comment.