File: gtm_c_stack_trace.c

package info (click to toggle)
fis-gtm 6.2-000-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 30,784 kB
  • ctags: 42,554
  • sloc: ansic: 358,483; asm: 4,847; csh: 4,574; sh: 2,261; awk: 200; makefile: 86; sed: 13
file content (147 lines) | stat: -rw-r--r-- 5,411 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/****************************************************************
 *								*
 *	Copyright 2012, 2014 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);
			}
		}
	}
}