1 // forktest.cpp                            Copyright (C) 2016-2020 Codemist
2 
3 //
4 // This file is NOT part of CSL. It is a test file used while testing
5 // development of support for any hypothetical future concurrency schemes.
6 //
7 
8 #include <sys/types.h>
9 #include <unistd.h>
10 #ifdef WIN32
11 #define SIGKILL 9
12 #else
13 #include <sys/wait.h>
14 #endif
15 #include <csignal>
16 #include <cerrno>
17 #include <cstdio>
18 #include <cstdlib>
19 
20 /**************************************************************************
21  * Copyright (C) 2020, Codemist.                         A C Norman       *
22  *                                                                        *
23  * Redistribution and use in source and binary forms, with or without     *
24  * modification, are permitted provided that the following conditions are *
25  * met:                                                                   *
26  *                                                                        *
27  *     * Redistributions of source code must retain the relevant          *
28  *       copyright notice, this list of conditions and the following      *
29  *       disclaimer.                                                      *
30  *     * Redistributions in binary form must reproduce the above          *
31  *       copyright notice, this list of conditions and the following      *
32  *       disclaimer in the documentation and/or other materials provided  *
33  *       with the distribution.                                           *
34  *                                                                        *
35  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS    *
36  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT      *
37  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS      *
38  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE         *
39  * COPYRIGHT OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,   *
40  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,   *
41  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS  *
42  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR  *
44  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF     *
45  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
46  * DAMAGE.                                                                *
47  *************************************************************************/
48 
49 // $Id: forktest.cpp 5433 2020-10-15 21:09:02Z arthurcnorman $
50 
51 
52 volatile int a = 0;
53 
worry(int n)54 void worry(int n)
55 {   int i, j;
56     for (j=0; j<100; j++)
57         for (i=0; i<10000000*n; i++) a++;
58 }
59 
main(int argc,char * argv[])60 int main(int argc, char *argv[])
61 {   pid_t pid1, pid2, pidx, pidy;
62     int status;
63     pid1 = fork();
64     if (pid1 < 0)
65     {   std::printf("Fork 1 failed\n");
66     }
67     else if (pid1 == 0)
68     {   // TASK 1
69         std::printf("Task 1 starting\n");
70         worry(argc+5);
71         std::printf("Task 1 has had %d seconds\n", argc+5);
72         std::exit(0);
73     }
74     else
75     {   std::printf("Task 1 has pid %d\n", pid1);
76         pid2 = fork();
77         if (pid2 < 0)
78         {   std::printf("Fork 2 failed\n");
79             kill(pid1, SIGKILL);
80             waitpid(pid1, &status, 0);
81             std::printf("Task 1 killed\n");
82         }
83         else if (pid2 == 0)
84         {   // TASK 2
85             std::printf("Task 2 starting\n");
86             worry(7);
87             std::printf("Task 2 has had 7 seconds\n");
88             std::exit(0);
89         }
90         else
91         {   std::printf("Task 2 has pid %d\n", pid2);
92             pidx = wait(&status);
93             std::printf("First signal was from task %d\n", pidx);
94             if (!WIFEXITED(status))
95             {   std::printf("Task did not exit cleanly\n");
96                 kill(pid1, SIGKILL);
97                 kill(pid2, SIGKILL);
98                 waitpid(pid1, &status, 0);
99                 waitpid(pid2, &status, 0);
100                 std::printf("Both tasks now dead\n");
101             }
102             pidy = pidx == pid1 ? pid2 : pid1;
103             kill(pidy, SIGKILL);
104             waitpid(pidy, &status, 0);
105             std::printf("Other task (%d) now dead\n", pidy);
106         }
107     }
108     std::printf("All done\n");
109     return 0;
110 }
111