@@ -26,6 +26,12 @@ static int upload(char *dir, int dirlen)
26
26
access ("HEAD" ,R_OK ))
27
27
return -1 ;
28
28
29
+ /*
30
+ * We'll ignore SIGTERM from now on, we have a
31
+ * good client.
32
+ */
33
+ signal (SIGTERM ,SIG_IGN );
34
+
29
35
/* git-upload-pack only ever reads stuff, so this is safe */
30
36
execlp ("git-upload-pack" ,"git-upload-pack" ,"." ,NULL );
31
37
return -1 ;
@@ -128,33 +134,24 @@ static void remove_child(pid_t pid, unsigned deleted, unsigned spawned)
128
134
*
129
135
* Really, this is just a place-holder for a _real_ algorithm.
130
136
*/
131
- static void kill_some_children (int connections ,unsigned start ,unsigned stop )
137
+ static void kill_some_children (int signo ,unsigned start ,unsigned stop )
132
138
{
133
139
start %=MAX_CHILDREN ;
134
140
stop %=MAX_CHILDREN ;
135
141
while (start != stop ) {
136
142
if (!(start & 3 ))
137
- kill (live_child [start ].pid ,SIGTERM );
143
+ kill (live_child [start ].pid ,signo );
138
144
start = (start + 1 ) %MAX_CHILDREN ;
139
145
}
140
146
}
141
147
142
- static void handle ( int incoming , struct sockaddr_in * addr , int addrlen )
148
+ static void check_max_connections ( void )
143
149
{
144
- pid_t pid = fork ();
145
-
146
- if (pid ) {
150
+ for (;;) {
147
151
int active ;
148
152
unsigned spawned ,reaped ,deleted ;
149
153
150
- close (incoming );
151
- if (pid < 0 )
152
- return ;
153
-
154
154
spawned = children_spawned ;
155
- add_child (spawned %MAX_CHILDREN ,pid ,addr ,addrlen );
156
- children_spawned = ++ spawned ;
157
-
158
155
reaped = children_reaped ;
159
156
deleted = children_deleted ;
160
157
@@ -166,15 +163,36 @@ static void handle(int incoming, struct sockaddr_in *addr, int addrlen)
166
163
children_deleted = deleted ;
167
164
168
165
active = spawned - deleted ;
169
- if (active > max_connections ) {
170
- kill_some_children ( active , deleted , spawned ) ;
166
+ if (active <= max_connections )
167
+ break ;
171
168
172
- /* Wait to make sure they're gone */
173
- while (spawned - children_reaped > max_connections )
174
- sleep (1 );
175
- }
176
-
169
+ /* Kill some unstarted connections with SIGTERM */
170
+ kill_some_children (SIGTERM ,deleted ,spawned );
171
+ if (active <=max_connections <<1 )
172
+ break ;
173
+
174
+ /* If the SIGTERM thing isn't helping use SIGKILL */
175
+ kill_some_children (SIGKILL ,deleted ,spawned );
176
+ sleep (1 );
177
+ }
178
+ }
179
+
180
+ static void handle (int incoming ,struct sockaddr_in * addr ,int addrlen )
181
+ {
182
+ pid_t pid = fork ();
183
+
184
+ if (pid ) {
185
+ unsigned idx ;
186
+
187
+ close (incoming );
188
+ if (pid < 0 )
189
+ return ;
190
+
191
+ idx = children_spawned %MAX_CHILDREN ;
192
+ children_spawned ++ ;
193
+ add_child (idx ,pid ,addr ,addrlen );
177
194
195
+ check_max_connections ();
178
196
return ;
179
197
}
180
198