148 lines
5.3 KiB
C
148 lines
5.3 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2012, 2013 Fidelity Information Services, Inc *
|
|
* *
|
|
* 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 *
|
|
* the license, please stop and do not read further. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
|
|
#include <errno.h>
|
|
#include <sys/un.h>
|
|
#include <signal.h>
|
|
#include <sys/wait.h>
|
|
#include "gtm_stdio.h" /* For SPRINTF */
|
|
#include "gtm_string.h"
|
|
#include "send_msg.h"
|
|
#include "wbox_test_init.h"
|
|
#include "gt_timer.h"
|
|
#include "gtm_logicals.h"
|
|
#include "trans_log_name.h"
|
|
#include "gdsroot.h"
|
|
#include "gdsbt.h"
|
|
#include "gdsfhead.h"
|
|
#include "gtm_c_stack_trace.h"
|
|
#include "jobsp.h" /* for MAX_PIDSTR_LEN */
|
|
#include "gtm_limits.h"
|
|
|
|
error_def(ERR_STUCKACT);
|
|
error_def(ERR_SYSCALL);
|
|
error_def(ERR_TEXT);
|
|
|
|
/* This looks up the environment variable gtm_procstuckexec, adds the calling information to it, passes it to a SYSTEM call
|
|
* and checks the returns from both the system and the invoked shell command
|
|
*/
|
|
void gtm_c_stack_trace(char *message, pid_t waiting_pid, pid_t blocking_pid, uint4 count)
|
|
{
|
|
int4 messagelen, arr_len;
|
|
char *command;
|
|
char *currpos;
|
|
int save_errno;
|
|
mstr envvar_logical, trans;
|
|
char buf[GTM_PATH_MAX];
|
|
int status;
|
|
# ifdef _BSD
|
|
union wait wait_stat;
|
|
# else
|
|
int4 wait_stat;
|
|
# endif
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
messagelen = STRLEN(message);
|
|
assert(SIZEOF(count) <= SIZEOF(pid_t));
|
|
arr_len = GTM_MAX_DIR_LEN + messagelen + (3 * MAX_PIDSTR_LEN) + 5; /* 4 spaces and a terminator */
|
|
if (!(TREF(gtm_waitstuck_script)).len)
|
|
{ /* uninitialized buffer - translate logical and move it to the buffer */
|
|
envvar_logical.addr = GTM_PROCSTUCKEXEC;
|
|
envvar_logical.len = SIZEOF(GTM_PROCSTUCKEXEC) - 1;
|
|
if (SS_NORMAL == (status = TRANS_LOG_NAME(&envvar_logical, &trans, buf, SIZEOF(buf), do_sendmsg_on_log2long)))
|
|
{ /* the environmental variable is defined */
|
|
assert(SIZEOF(buf) > trans.len);
|
|
if (0 != trans.len)
|
|
{ /* and it has a value - stick the length of the translation in char_len of mstr */
|
|
(TREF(gtm_waitstuck_script)).len = trans.len + arr_len;
|
|
(TREF(gtm_waitstuck_script)).addr
|
|
= (char *)malloc((TREF(gtm_waitstuck_script)).len);
|
|
memcpy((TREF(gtm_waitstuck_script)).addr, trans.addr, trans.len);
|
|
*(char *)((TREF(gtm_waitstuck_script)).addr + trans.len) = ' ';
|
|
trans.len += 1;
|
|
(TREF(gtm_waitstuck_script)).char_len = trans.len; /* abuse of mstr to hold second length */
|
|
}
|
|
}
|
|
} else
|
|
{ /* already have a pointer to the shell command get its length */
|
|
trans.len = (TREF(gtm_waitstuck_script)).char_len;
|
|
assert(0 < trans.len);
|
|
if ((trans.len + arr_len) > (TREF(gtm_waitstuck_script)).len)
|
|
{ /* new message doesn't fit - malloc fresh space and free the old */
|
|
(TREF(gtm_waitstuck_script)).len = trans.len + arr_len;
|
|
trans.addr = (char *)malloc((TREF(gtm_waitstuck_script)).len);
|
|
memcpy(trans.addr, (TREF(gtm_waitstuck_script)).addr, trans.len);
|
|
free((TREF(gtm_waitstuck_script)).addr);
|
|
(TREF(gtm_waitstuck_script)).addr = trans.addr;
|
|
}
|
|
}
|
|
if (0 != (TREF(gtm_waitstuck_script)).len)
|
|
{ /* have a command and a message */
|
|
command = (TREF(gtm_waitstuck_script)).addr;
|
|
currpos = command + trans.len;
|
|
memcpy(currpos, message, messagelen);
|
|
currpos += messagelen;
|
|
*currpos++ = ' ';
|
|
currpos = (char *)i2asc((unsigned char*)currpos, (unsigned int)waiting_pid);
|
|
*currpos++ = ' ';
|
|
currpos = (char *)i2asc((unsigned char*)currpos, (unsigned int)blocking_pid);
|
|
*currpos++ = ' ';
|
|
currpos = (char *)i2asc((unsigned char*)currpos, (unsigned int)count);
|
|
*currpos++ = 0;
|
|
assert(currpos - (TREF(gtm_waitstuck_script)).addr <= (TREF(gtm_waitstuck_script)).len);
|
|
status = SYSTEM(((char *)((TREF(gtm_waitstuck_script)).addr)));
|
|
if (-1 == status)
|
|
{ /* SYSTEM failed */
|
|
save_errno = errno;
|
|
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4, LEN_AND_LIT("FAILURE"), LEN_AND_STR(command));
|
|
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("system"), CALLFROM, save_errno);
|
|
} else
|
|
{ /* check on how the command did */
|
|
assert(SIZEOF(wait_stat) == SIZEOF(int4));
|
|
# ifdef _BSD
|
|
wait_stat.w_status = status;
|
|
# else
|
|
wait_stat = status;
|
|
# endif
|
|
if (WIFEXITED(wait_stat))
|
|
{
|
|
status = WEXITSTATUS(wait_stat);
|
|
if (!status)
|
|
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4,
|
|
LEN_AND_LIT("SUCCESS"), LEN_AND_STR(command));
|
|
else
|
|
{
|
|
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4,
|
|
LEN_AND_LIT("FAILURE"), LEN_AND_STR(command));
|
|
if (WIFSIGNALED(wait_stat))
|
|
{
|
|
status = WTERMSIG(wait_stat);
|
|
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
|
|
LEN_AND_LIT("PROCSTUCK terminated by signal"), CALLFROM, status);
|
|
} else
|
|
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
|
|
LEN_AND_LIT("PROCSTUCK"), CALLFROM, status);
|
|
}
|
|
} else
|
|
{ /* it's gone rogue' */
|
|
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4,
|
|
LEN_AND_LIT("FAILURE"), LEN_AND_STR(command));
|
|
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
|
|
LEN_AND_LIT("PROCSTUCK did not report status"), CALLFROM, status);
|
|
assert(FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|