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, 4 months ago) by tdb
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
State: FILE REMOVED
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

# User Rev Content
1 ab11 1.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     }