asynchronous event handling loop. test12.
[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.11 2005/02/09 03:27:49 jaw 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     if (pid >= 0) {
132         /* both parent and child exit here */
133         func2_2();
134         dprintf("at exit of %d, globalVariable2_1 = %d\n", (int) getpid(),
135                 globalVariable2_1);
136
137 #if defined(rs6000_ibm_aix4_1)
138         if( pid == 0){
139                 /* On AIX the child dies when the parent exits, so wait */
140                 /* apparently the parent needs to wake up occasionally to keep Dyninst happy */
141                 dprintf("%d SLEEPING\n",getpid());
142                 sleep(5);
143                 dprintf("%d SLEEP MORE\n",getpid());
144                 sleep(1);
145                 dprintf("%d SLEEP MORE\n",getpid());
146                 sleep(5);
147                 dprintf("%d DONE SLEEPING\n",getpid());
148         }
149 #endif
150
151         dprintf("Mutatee %d exiting...\n", getpid());
152         exit(getpid());
153     } else if (pid < 0) {
154         /* error case */
155         exit(pid);
156     }
157 #endif
158 }
159
160 unsigned int globalVariable3_1 = 0xdeadbeef;
161
162 void func3_1(int argc, char *argv[])
163 {
164     int i;
165     char *ch;
166     char **newArgv;
167
168     newArgv = (char **) calloc(sizeof(char *), argc +1);
169     for (i = 0; i < argc; i++) newArgv[i] = argv[i];
170
171     /* replace 4a in copy of myName by 4b */
172     newArgv[0] = strdup(argv[0]);
173     for (ch=newArgv[0]; *ch; ch++) {
174         if (!strncmp(ch, "4a", 2)) *(ch+1) = 'b';
175     }
176
177     globalVariable3_1 = 3000001;
178     dprintf("Starting \"%s\"\n", newArgv[0]);
179     errno = 0;
180     execvp(newArgv[0], newArgv);
181     perror("execvp");
182 }
183
184 unsigned int globalVariable4_1 = 0xdeadbeef;
185
186 void func4_3()
187 {
188     dprintf("in func4_3\n");
189     globalVariable4_1 = 4000002;
190 }
191
192 void func4_2()
193 {
194     dprintf("in func4_2\n");
195     /* call to func4_3 should be inserted here */
196 }
197
198 void func4_1(int argc, char *argv[])
199 {
200 #ifndef i386_unknown_nt4_0
201     int i;
202     int pid;
203     char *ch;
204     char **newArgv;
205
206     pid = fork();
207     if (pid == 0) {
208         newArgv = (char**) calloc(sizeof(char *), argc +1);
209         for (i = 0; i < argc; i++) newArgv[i] = argv[i];
210         
211         /* replace 4a in copy of myName by 4b */
212         newArgv[0] = strdup(argv[0]);
213         for (ch=newArgv[0]; *ch; ch++) {
214             if (!strncmp(ch, "4a", 2)) *(ch+1) = 'b';
215         }
216         
217         globalVariable3_1 = 3000001;
218         dprintf("Starting \"%s\"\n", newArgv[0]);
219         execvp(newArgv[0], newArgv);
220         perror("execvp");
221     } else {
222         func4_2();
223 #if defined(rs6000_ibm_aix4_1)
224         /* On AIX the child dies when the parent exits, so wait */
225         /* and the parent needs to wake up occasionally to keep dyninst happy*/
226         dprintf("%d SLEEPING\n",getpid());
227         sleep(10);
228         dprintf("%d SLEEP MORE\n",getpid());
229         sleep(2);
230         dprintf("%d SLEEP MORE\n",getpid());
231         sleep(5);
232         dprintf("%d DONE SLEEPING\n",getpid());
233
234 #endif
235         exit(getpid());
236     }
237 #endif
238 }
239
240 int main(int argc, char *argv[])
241 {                                       
242     int i, j;
243
244     for (i=1; i < argc; i++) {
245         if (!strcmp(argv[i], "-verbose")) {
246             debugPrint = TRUE;
247         } else if (!strcmp(argv[i], "-run")) {
248             runAllTests = FALSE;
249             for (j=0; j <= MAX_TEST; j++) runTest[j] = FALSE;
250             for (j=i+1; j < argc; j++) {
251                 unsigned int testId;
252                 if ((testId = atoi(argv[j]))) {
253                     if ((testId > 0) && (testId <= MAX_TEST)) {
254                         runTest[testId] = TRUE;
255                     } else {
256                         printf("invalid test %d requested\n", testId);
257                         exit(-1);
258                     }
259                 } else {
260                     /* end of test list */
261                     break;
262                 }
263             }
264             i=j-1;
265         } else {
266             fprintf(stderr, "Usage: %s [-verbose] -run <num> ..\n", argv[0]);
267             exit(-1);
268         }
269     }
270
271     if ((argc==1) || debugPrint)
272         printf("Mutatee %s [%s]:\"%s\"\n", argv[0], 
273                 mutateeCplusplus ? "C++" : "C", Builder_id);
274     if (argc==1) exit(0);
275
276     if (runTest[1]) func1_1();
277     if (runTest[2]) func2_1();
278     if (runTest[3]) func3_1(argc, argv);
279     if (runTest[4]) func4_1(argc, argv);
280
281     dprintf("Mutatee %s terminating.\n", argv[0]);
282     return 0;
283 }