ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/host/c++/socket++-1.10/Fork.C
Revision: 1.2
Committed: Mon Jun 10 14:10:43 2002 UTC (22 years, 5 months ago) by tdb
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
State: FILE REMOVED
Error occurred while calculating annotation data.
Log Message:
Tidy up of files. These are all old things that are not only no longer used
but are also probably useless to anyone other than us. This saves checking
them out all the time, and makes the "cms/source" tree contain only current
stuff. They'll still exist in the attic's though :)

File Contents

# Content
1 // Fork.C -*- C++ -*- socket library
2 // Copyright (C) 1992,1993,1994 Gnanasekaran Swaminathan <gs4t@virginia.edu>
3 //
4 // Permission is granted to use at your own risk and distribute this software
5 // in source and binary forms provided the above copyright
6 // notice and this paragraph are preserved on all copies.
7 // This software is provided "as is" with no express or implied warranty.
8 //
9 // Version: 17Oct95 1.10
10
11 #include <config.h>
12
13 #include <iostream.h>
14 #include <stdio.h> // perror in solaris2.3 is declared here
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <errno.h>
18 #include <signal.h>
19 #include <sys/wait.h>
20
21 #include <Fork.h>
22
23 Fork::ForkProcess* Fork::ForkProcess::list = 0;
24 Fork::KillForks Fork::killall;
25
26 Fork::~Fork ()
27 {
28 if (process->pid <= 0)
29 delete process;
30 }
31
32 Fork::KillForks::~KillForks ()
33 // First, kill all children whose kill_child flag is set.
34 // Second, wait for other children to die.
35 {
36 for (ForkProcess* cur = Fork::ForkProcess::list; cur; cur = cur->next)
37 if (cur->kill_child)
38 delete cur;
39
40 while (Fork::ForkProcess::list && wait (0) > 0);
41 }
42
43 Fork::ForkProcess::ForkProcess (int kill, int give_reason)
44 : kill_child (kill), reason (give_reason), next (0)
45 {
46 if (list == 0) {
47 struct sigaction sa;
48 sa.sa_handler = funcptr (&Fork::ForkProcess::reaper_nohang);
49 sigemptyset (&sa.sa_mask);
50 sa.sa_flags = SA_RESTART;
51 sigaction (SIGCHLD, &sa, 0);
52 }
53
54 pid = fork ();
55
56 if (pid > 0) {
57 next = list;
58 list = this;
59 } else if (pid == 0) {
60 // child process. clear list
61 ForkProcess* p = list;
62 while (p) {
63 ForkProcess* nxt = p->next;
64 p->pid = 0;
65 delete p;
66 p = nxt;
67 }
68 list = 0;
69
70 if (kill_child) {
71 struct sigaction sa;
72 sa.sa_handler = funcptr (&Fork::ForkProcess::commit_suicide);
73 sigemptyset (&sa.sa_mask);
74 sa.sa_flags = SA_RESTART;
75 sigaction (SIGTERM, &sa, 0);
76 }
77 }
78 }
79
80 Fork::ForkProcess::~ForkProcess ()
81 {
82 if (pid > 0) {
83 if (kill_child)
84 kill (pid, SIGTERM);
85 reap_child ();
86
87 // I remove myself from list
88 if (list == this)
89 list = list->next;
90 else {
91 for (ForkProcess* p = list; p; p = p->next)
92 if (p->next == this) {
93 p->next = next;
94 break;
95 }
96 }
97 }
98 }
99
100 void Fork::ForkProcess::kill_process () const
101 {
102 if (pid > 0) {
103 kill (pid, SIGKILL);
104 reap_child ();
105 }
106 }
107
108 void Fork::ForkProcess::reap_child () const
109 {
110 int status;
111 if (pid > 0 && waitpid (pid, &status, 0) == pid && reason)
112 infanticide_reason (pid, status);
113 }
114
115 void Fork::ForkProcess::infanticide_reason (pid_t pid, int status)
116 {
117 if (pid <= 0)
118 return;
119
120 if (WIFSTOPPED (status))
121 cerr << "process " << pid << " gets "
122 << SYS_SIGLIST [WSTOPSIG (status)] << endl;
123 else if (WIFEXITED (status))
124 cerr << "process " << pid << " exited with status "
125 << WEXITSTATUS (status) << endl;
126 else if (WIFSIGNALED (status))
127 cerr << "process " << pid << " got "
128 << SYS_SIGLIST [WTERMSIG (status)] << endl;
129 }
130
131 void Fork::ForkProcess::reaper_nohang (int signo)
132 {
133 if (signo != SIGCHLD)
134 return;
135
136 int status;
137 pid_t wpid;
138 if ((wpid = waitpid (-1, &status, WNOHANG)) > 0) {
139 ForkProcess* prev = 0;
140 ForkProcess* cur = list;
141 while (cur) {
142 if (cur->pid == wpid) {
143 cur->pid = -1;
144 if (prev)
145 prev->next = cur->next;
146 else
147 list = list->next;
148
149 if (cur->reason)
150 infanticide_reason (wpid, status);
151
152 delete cur;
153 break;
154 }
155 prev = cur;
156 cur = cur->next;
157 }
158 }
159 }
160
161 void Fork::ForkProcess::commit_suicide (int)
162 {
163 // if this process has any children we kill them.
164
165 ForkProcess* p = list;
166 while (p) {
167 ForkProcess* next = p->next;
168 if (!p->kill_child) // otherwise ForkProcess::~ForkProcess will take care
169 kill (p->pid, SIGKILL);
170 delete p; // ForkProcess::~ForkProcess will call reap_child ().
171 p = next;
172 }
173
174 exit (0x0f);
175 }
176
177 void Fork::suicide_signal (int signo)
178 // commit suicide at the signal signo
179 {
180 struct sigaction sa;
181 sa.sa_handler = funcptr (&Fork::ForkProcess::commit_suicide);
182 sigemptyset (&sa.sa_mask);
183 sa.sa_flags = 0;
184 if (sigaction (signo, &sa, 0) == -1)
185 perror ("Fork: Cannot commit suicide with the specified signal");
186 }