Fixes for races in test4, delete signal handler threads - - - - - - - -
[dyninst.git] / dyninstAPI / tests / src / test4a.mutatee.c
1 /*
2  * Copyright (c) 1996-2004 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /* Test application (Mutatee) */
43
44 /* $Id: test4a.mutatee.c,v 1.12 2006/02/08 23:41:33 bernat Exp $ */
45
46 #include <stdio.h>
47 #include <assert.h>
48 #include <sys/types.h>
49 #include <signal.h>
50 #include <string.h>
51 #include <stdlib.h>
52 #include <stdarg.h>
53 #include <errno.h>
54
55 #if defined(i386_unknown_nt4_0) && !defined(__GNUC__)
56 #define WIN32_LEAN_AND_MEAN
57 #include <windows.h>
58 #include <process.h>
59 #define getpid _getpid
60 #else
61 #include <unistd.h>
62 #endif
63
64 #ifdef __cplusplus
65 int mutateeCplusplus = 1;
66 #else
67 int mutateeCplusplus = 0;
68 #endif
69
70 #ifndef COMPILER
71 #define COMPILER ""
72 #endif
73 const char *Builder_id=COMPILER; /* defined on compile line */
74
75 int debugPrint = 0;
76
77 /* control debug printf statements */
78 void dprintf(const char *fmt, ...) {
79    va_list args;
80    va_start(args, fmt);
81
82    if(debugPrint)
83       vfprintf(stderr, fmt, args);
84
85    va_end(args);
86
87    fflush(stderr);
88 }
89
90 #define TRUE    1
91 #define FALSE   0
92
93 int runAllTests = TRUE;
94 #define MAX_TEST 5
95 int runTest[MAX_TEST+1];
96
97 unsigned int globalVariable1_1 = 0xdeadbeef;
98 unsigned int globalVariable2_1 = 0xdeadbeef;
99
100 void func1_1()
101 {
102     globalVariable1_1 = 1000001;
103     exit((int) getpid());
104 }
105
106 /* should be called by parent */
107 void func2_3()
108 {
109     dprintf("pid %d in func2_3\n", (int) getpid());
110     globalVariable2_1 = 2000002;
111 }
112
113 /* should be called by child */
114 void func2_4()
115 {
116     dprintf("pid %d in func2_4\n", (int) getpid());
117     globalVariable2_1 = 2000003;
118 }
119
120 void func2_2() {
121     /* if we get this value at exit, no function was called */
122     globalVariable2_1 = 2000001;
123 }
124
125 void func2_1()
126 {
127 #ifndef i386_unknown_nt4_0
128     int pid;
129
130     pid = fork();
131     dprintf("fork result: %d\n", pid);
132     if (pid >= 0) {
133         /* both parent and child exit here */
134         func2_2();
135         dprintf("at exit of %d, globalVariable2_1 = %d\n", (int) getpid(),
136                 globalVariable2_1);
137
138 #if defined(rs6000_ibm_aix4_1)
139         if( pid == 0){
140                 /* On AIX the child dies when the parent exits, so wait */
141                 /* apparently the parent needs to wake up occasionally to keep Dyninst happy */
142                 dprintf("%d SLEEPING\n",getpid());
143                 sleep(5);
144                 dprintf("%d SLEEP MORE\n",getpid());
145                 sleep(1);
146                 dprintf("%d SLEEP MORE\n",getpid());
147                 sleep(5);
148                 dprintf("%d DONE SLEEPING\n",getpid());
149         }
150 #endif
151         
152         /* Make the parent exit first (again, testing) */
153         if (pid == 0)
154             sleep(5);
155
156         dprintf("Mutatee %d exiting...\n", getpid());
157         exit(getpid());
158     } else if (pid < 0) {
159         /* error case */
160         exit(pid);
161     }
162 #endif
163 }
164
165 unsigned int globalVariable3_1 = 0xdeadbeef;
166
167 void func3_1(int argc, char *argv[])
168 {
169     int i;
170     char *ch;
171     char **newArgv;
172
173     newArgv = (char **) calloc(sizeof(char *), argc +1);
174     for (i = 0; i < argc; i++) newArgv[i] = argv[i];
175
176     /* replace 4a in copy of myName by 4b */
177     newArgv[0] = strdup(argv[0]);
178     for (ch=newArgv[0]; *ch; ch++) {
179         if (!strncmp(ch, "4a", 2)) *(ch+1) = 'b';
180     }
181
182     globalVariable3_1 = 3000001;
183     dprintf("Starting \"%s\"\n", newArgv[0]);
184     errno = 0;
185     dprintf("Going into exec...\n");
186     execvp(newArgv[0], newArgv);
187     perror("execvp");
188 }
189
190 unsigned int globalVariable4_1 = 0xdeadbeef;
191
192 void func4_3()
193 {
194     dprintf("in func4_3\n");
195     globalVariable4_1 = 4000002;
196 }
197
198 void func4_2()
199 {
200     dprintf("in func4_2\n");
201     /* call to func4_3 should be inserted here */
202 }
203
204 void func4_1(int argc, char *argv[])
205 {
206 #ifndef i386_unknown_nt4_0
207     int i;
208     int pid;
209     char *ch;
210     char **newArgv;
211
212     pid = fork();
213     if (pid == 0) {
214         newArgv = (char**) calloc(sizeof(char *), argc +1);
215         for (i = 0; i < argc; i++) newArgv[i] = argv[i];
216         
217         /* replace 4a in copy of myName by 4b */
218         newArgv[0] = strdup(argv[0]);
219         for (ch=newArgv[0]; *ch; ch++) {
220             if (!strncmp(ch, "4a", 2)) *(ch+1) = 'b';
221         }
222         
223         globalVariable3_1 = 3000001;
224         dprintf("Starting \"%s\"\n", newArgv[0]);
225         execvp(newArgv[0], newArgv);
226         perror("execvp");
227     } else {
228         func4_2();
229 #if defined(rs6000_ibm_aix4_1)
230         /* On AIX the child dies when the parent exits, so wait */
231         /* and the parent needs to wake up occasionally to keep dyninst happy*/
232         dprintf("%d SLEEPING\n",getpid());
233         sleep(10);
234         dprintf("%d SLEEP MORE\n",getpid());
235         sleep(2);
236         dprintf("%d SLEEP MORE\n",getpid());
237         sleep(5);
238         dprintf("%d DONE SLEEPING\n",getpid());
239
240 #endif
241         exit(getpid());
242     }
243 #endif
244 }
245
246 int main(int argc, char *argv[])
247 {                                       
248     int i, j;
249
250     for (i=1; i < argc; i++) {
251         if (!strcmp(argv[i], "-verbose")) {
252             debugPrint = TRUE;
253         } else if (!strcmp(argv[i], "-run")) {
254             runAllTests = FALSE;
255             for (j=0; j <= MAX_TEST; j++) runTest[j] = FALSE;
256             for (j=i+1; j < argc; j++) {
257                 unsigned int testId;
258                 if ((testId = atoi(argv[j]))) {
259                     if ((testId > 0) && (testId <= MAX_TEST)) {
260                         runTest[testId] = TRUE;
261                     } else {
262                         printf("invalid test %d requested\n", testId);
263                         exit(-1);
264                     }
265                 } else {
266                     /* end of test list */
267                     break;
268                 }
269             }
270             i=j-1;
271         } else {
272             fprintf(stderr, "Usage: %s [-verbose] -run <num> ..\n", argv[0]);
273             exit(-1);
274         }
275     }
276
277     if ((argc==1) || debugPrint)
278         printf("Mutatee %s [%s]:\"%s\"\n", argv[0], 
279                 mutateeCplusplus ? "C++" : "C", Builder_id);
280     if (argc==1) exit(0);
281
282     if (runTest[1]) func1_1();
283     if (runTest[2]) func2_1();
284     if (runTest[3]) func3_1(argc, argv);
285     if (runTest[4]) func4_1(argc, argv);
286
287     dprintf("Mutatee %s terminating.\n", argv[0]);
288     return 0;
289 }