ruby-lsapi 4.1 → 5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZTBmYTY2NTdiZDk3NjAxNTViYmExOTc4ZDU5ZjJhYjk1MmFmNjhiZA==
5
- data.tar.gz: !binary |-
6
- YmRkNDNhMGZiMmI5Y2I2YjQ0M2Q4OTkzZWVhMjRkMmFmZjA4ZDFlYQ==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- NTg2NGQ5Zjc1NWUyYTExNDUzMTYzN2VhODAyMDI4N2Y0MDFhMTBiMThkMWNm
10
- MWU3NDY0Njg4MzcxZDUyYmYzYjJjMjIyYTUxNGU4YTUyOGQ1ZDIxZDg1YWJh
11
- YjZlNDJlNTJhMWJkMzZiOWVjMmE2ODQ2ZGNmMTkzMzk1MDRhMDg=
12
- data.tar.gz: !binary |-
13
- MzBmZDNhMmY5NGQ3NWY0NmJmMDIyMTgzNTUyMDBhZDczMzM2Y2MwY2I5YzAx
14
- NGYxN2M0OWEyYTQ1YjYzNTEwNzlmNGQ3ZGY4ZDU1MGM3MTQ2NThlZDkwODBi
15
- MjExZWRkOWIxZTI1NGVjMWEwMDNmYzBkNTBjMTBhNmFlZTc5ZTM=
2
+ SHA256:
3
+ metadata.gz: 665d989d50ec0e54915439997a1a09c0eb77c6bfdc0e1bf86dc96096b8eaab4a
4
+ data.tar.gz: 0fc93aa398f8f0bf7ef5b566cbd0504f509d6b3f80eb6a1532f719ab1b296f51
5
+ SHA512:
6
+ metadata.gz: 4ad0661c05da99577c6a8a0974a49e5621c250b498122b6b8acb045dc1076a1e8413f65af66c3b3c78c169b28ab2180ff72db08339c8f8311059c8086223bfbd
7
+ data.tar.gz: facafedc4aa6c30e1f7007188d743b1a47c919eef452a17119065e0ce47bee4be551fc017521de61cf9685c901494e042a254216c663ca88ff088bdff206d636
@@ -6,4 +6,7 @@ end
6
6
  if RUBY_VERSION =~ /1.9/ then
7
7
  $CPPFLAGS += " -DRUBY_19"
8
8
  end
9
+ if RUBY_VERSION =~ /2/ then
10
+ $CPPFLAGS += " -DRUBY_2"
11
+ end
9
12
  create_makefile( "lsapi" )
@@ -1,21 +1,21 @@
1
1
  /*
2
- Copyright (c) 2005, Lite Speed Technologies Inc.
2
+ Copyright (c) 2002-2018, Lite Speed Technologies Inc.
3
3
  All rights reserved.
4
4
 
5
5
  Redistribution and use in source and binary forms, with or without
6
6
  modification, are permitted provided that the following conditions are
7
- met:
7
+ met:
8
8
 
9
9
  * Redistributions of source code must retain the above copyright
10
- notice, this list of conditions and the following disclaimer.
10
+ notice, this list of conditions and the following disclaimer.
11
11
  * Redistributions in binary form must reproduce the above
12
12
  copyright notice, this list of conditions and the following
13
13
  disclaimer in the documentation and/or other materials provided
14
- with the distribution.
14
+ with the distribution.
15
15
  * Neither the name of the Lite Speed Technologies Inc nor the
16
16
  names of its contributors may be used to endorse or promote
17
17
  products derived from this software without specific prior
18
- written permission.
18
+ written permission.
19
19
 
20
20
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
21
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -27,16 +27,9 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
27
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
28
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
29
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
31
  */
32
32
 
33
- /***************************************************************************
34
- $Id: lsapidef.h,v 1.17 2012/12/01 19:23:31 gwang Exp $
35
- -------------------
36
- begin : Thu Feb 10 2005
37
- author : George Wang
38
- email : gwang@litespeedtech.com
39
- ***************************************************************************/
40
33
 
41
34
  #ifndef _LSAPIDEF_H_
42
35
  #define _LSAPIDEF_H_
@@ -83,7 +76,7 @@ enum
83
76
 
84
77
  /* Values for m_flag in lsapi_packet_header */
85
78
  #define LSAPI_ENDIAN_LITTLE 0
86
- #define LSAPI_ENDIAN_BIG 1
79
+ #define LSAPI_ENDIAN_BIG 1
87
80
  #define LSAPI_ENDIAN_BIT 1
88
81
 
89
82
  #if defined(__i386__)||defined( __x86_64 )||defined( __x86_64__ )
@@ -126,7 +119,7 @@ struct lsapi_packet_header
126
119
 
127
120
  /*
128
121
  LSAPI request header packet
129
-
122
+
130
123
  1. struct lsapi_req_header
131
124
  2. struct lsapi_http_header_index
132
125
  3. lsapi_header_offset * unknownHeaders
@@ -137,7 +130,7 @@ struct lsapi_packet_header
137
130
  struct lsapi_req_header
138
131
  {
139
132
  struct lsapi_packet_header m_pktHeader;
140
-
133
+
141
134
  int32_t m_httpHeaderLen;
142
135
  int32_t m_reqBodyLen;
143
136
  int32_t m_scriptFileOff; /* path to the script file. */
@@ -151,11 +144,11 @@ struct lsapi_req_header
151
144
 
152
145
 
153
146
  struct lsapi_http_header_index
154
- {
155
- int16_t m_headerLen[H_TRANSFER_ENCODING+1];
147
+ {
148
+ uint16_t m_headerLen[H_TRANSFER_ENCODING+1];
156
149
  int32_t m_headerOff[H_TRANSFER_ENCODING+1];
157
- } ;
158
-
150
+ } ;
151
+
159
152
  struct lsapi_header_offset
160
153
  {
161
154
  int32_t nameOff;
@@ -1,21 +1,22 @@
1
+ //#define LSAPI_DEBUG
1
2
  /*
2
- Copyright (c) 2005, Lite Speed Technologies Inc.
3
+ Copyright (c) 2002-2018, Lite Speed Technologies Inc.
3
4
  All rights reserved.
4
5
 
5
6
  Redistribution and use in source and binary forms, with or without
6
7
  modification, are permitted provided that the following conditions are
7
- met:
8
+ met:
8
9
 
9
10
  * Redistributions of source code must retain the above copyright
10
- notice, this list of conditions and the following disclaimer.
11
+ notice, this list of conditions and the following disclaimer.
11
12
  * Redistributions in binary form must reproduce the above
12
13
  copyright notice, this list of conditions and the following
13
14
  disclaimer in the documentation and/or other materials provided
14
- with the distribution.
15
+ with the distribution.
15
16
  * Neither the name of the Lite Speed Technologies Inc nor the
16
17
  names of its contributors may be used to endorse or promote
17
18
  products derived from this software without specific prior
18
- written permission.
19
+ written permission.
19
20
 
20
21
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
22
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -27,27 +28,21 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
28
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
29
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
30
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32
  */
32
33
 
33
- /***************************************************************************
34
- lsapilib.c - description
35
- -------------------
36
- begin : Mon Feb 21 2005
37
- copyright : (C) 2005 by George Wang
38
- email : gwang@litespeedtech.com
39
- ***************************************************************************/
40
-
41
34
 
42
35
  #include <ctype.h>
43
36
  #include <dlfcn.h>
44
37
  #include <errno.h>
45
38
  #include <fcntl.h>
46
-
39
+ #include <limits.h>
47
40
  #include <sys/stat.h>
41
+ #include <sched.h>
48
42
  #include <signal.h>
49
43
  #include <stdlib.h>
50
44
  #include <stdio.h>
45
+ #include <stdarg.h>
51
46
  #include <string.h>
52
47
  #include <sys/mman.h>
53
48
  #include <sys/resource.h>
@@ -102,25 +97,70 @@ typedef struct lsapi_MD5Context lsapi_MD5_CTX;
102
97
  #define LSAPI_ST_REQ_BODY 2
103
98
  #define LSAPI_ST_RESP_HEADER 4
104
99
  #define LSAPI_ST_RESP_BODY 8
100
+ #define LSAPI_ST_BACKGROUND 16
105
101
 
106
102
  #define LSAPI_RESP_BUF_SIZE 8192
107
103
  #define LSAPI_INIT_RESP_HEADER_LEN 4096
108
104
 
105
+ enum
106
+ {
107
+ LSAPI_STATE_IDLE,
108
+ LSAPI_STATE_CONNECTED,
109
+ LSAPI_STATE_ACCEPTING,
110
+ };
111
+
112
+ typedef struct lsapi_child_status
113
+ {
114
+ int m_pid;
115
+ long m_tmStart;
116
+
117
+ volatile short m_iKillSent;
118
+ volatile char m_inProcess;
119
+ volatile char m_state;
120
+ volatile int m_iReqCounter;
121
+
122
+ volatile long m_tmWaitBegin;
123
+ volatile long m_tmReqBegin;
124
+ volatile long m_tmLastCheckPoint;
125
+ }
126
+ lsapi_child_status;
109
127
 
128
+ static lsapi_child_status * s_worker_status = NULL;
110
129
 
111
130
  static int g_inited = 0;
112
131
  static int g_running = 1;
113
132
  static int s_ppid;
133
+ static int s_restored_ppid = 0;
134
+ static int s_pid = 0;
114
135
  static int s_slow_req_msecs = 0;
115
136
  static int s_keepListener = 0;
116
137
  static int s_dump_debug_info = 0;
138
+ static int s_pid_dump_debug_info = 0;
139
+ static int s_req_processed = 0;
140
+ static int s_skip_write = 0;
141
+ static int (*pthread_atfork_func)(void (*prepare)(void), void (*parent)(void),
142
+ void (*child)(void)) = NULL;
117
143
 
118
- LSAPI_Request g_req = { -1, -1 };
144
+ static int *s_busy_workers = NULL;
145
+ static int *s_accepting_workers = NULL;
146
+ static int *s_global_counter = &s_req_processed;
147
+ static int s_max_busy_workers = -1;
148
+ static char *s_stderr_log_path = NULL;
149
+ static int s_stderr_is_pipe = 0;
150
+ static int s_ignore_pid = -1;
151
+ static size_t s_total_pages = 1;
152
+ static size_t s_min_avail_pages = 256 * 1024;
153
+ static size_t *s_avail_pages = &s_total_pages;
119
154
 
120
- static char s_pSecret[24];
155
+ LSAPI_Request g_req =
156
+ { .m_fdListen = -1, .m_fd = -1 };
121
157
 
158
+ static char s_secret[24];
159
+
160
+ static LSAPI_On_Timer_pf s_proc_group_timer_cb = NULL;
122
161
 
123
162
  void Flush_RespBuf_r( LSAPI_Request * pReq );
163
+ static int lsapi_reopen_stderr(const char *p);
124
164
 
125
165
  static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
126
166
  {
@@ -142,7 +182,7 @@ static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
142
182
  "HTTP_VIA",
143
183
  "HTTP_TRANSFER_ENCODING"
144
184
  };
145
-
185
+
146
186
  static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] =
147
187
  { 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
148
188
  22, 13, 18, 13, 24, 15, 10, 20, 8, 22 };
@@ -173,10 +213,102 @@ static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] =
173
213
  { 6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent
174
214
  13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
175
215
  };
176
-
216
+
217
+
218
+ static const char *s_log_level_names[8] =
219
+ {
220
+ "", "DEBUG","INFO", "NOTICE", "WARN", "ERROR", "CRIT", "FATAL"
221
+ };
222
+
223
+
224
+ void LSAPI_Log(int flag, const char * fmt, ...)
225
+ {
226
+ char buf[1024];
227
+ char *p = buf;
228
+ if ((flag & LSAPI_LOG_TIMESTAMP_BITS)
229
+ && !(s_stderr_is_pipe))
230
+ {
231
+ struct timeval tv;
232
+ struct tm tm;
233
+ gettimeofday(&tv, NULL);
234
+ localtime_r(&tv.tv_sec, &tm);
235
+ if (flag & LSAPI_LOG_TIMESTAMP_FULL)
236
+ {
237
+ p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%06d ",
238
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
239
+ tm.tm_hour, tm.tm_min, tm.tm_sec, (int)tv.tv_usec);
240
+ }
241
+ else if (flag & LSAPI_LOG_TIMESTAMP_HMS)
242
+ {
243
+ p += snprintf(p, 1024, "%02d:%02d:%02d ",
244
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
245
+ }
246
+ }
247
+
248
+ int level = flag & LSAPI_LOG_LEVEL_BITS;
249
+ if (level && level <= LSAPI_LOG_FLAG_FATAL)
250
+ {
251
+ p += snprintf(p, 100, "[%s] ", s_log_level_names[level]);
252
+ }
253
+
254
+ if (flag & LSAPI_LOG_PID)
255
+ {
256
+ p += snprintf(p, 100, "[UID:%d][%d] ", getuid(), s_pid);
257
+ }
258
+
259
+ if (p > buf)
260
+ fprintf(stderr, "%.*s", (int)(p - buf), buf);
261
+ va_list ap;
262
+ va_start(ap, fmt);
263
+ vfprintf(stderr, fmt, ap);
264
+ va_end(ap);
265
+ }
266
+
267
+ #ifdef LSAPI_DEBUG
268
+
269
+ #define DBGLOG_FLAG (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_DEBUG|LSAPI_LOG_PID)
270
+ #define lsapi_dbg(...) LSAPI_Log(DBGLOG_FLAG, __VA_ARGS__)
271
+
272
+ #else
273
+
274
+ #define lsapi_dbg(...)
275
+
276
+ #endif
277
+
278
+ #define lsapi_log(...) LSAPI_Log(LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_PID, __VA_ARGS__)
279
+
280
+
281
+ void lsapi_perror(const char * pMessage, int err_no)
282
+ {
283
+ lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no, strerror(err_no));
284
+ }
285
+
286
+
287
+ static int lsapi_parent_dead()
288
+ {
289
+ // Return non-zero if the parent is dead. 0 if still alive.
290
+ if (!s_ppid) {
291
+ // not checking, so not dead
292
+ return(0);
293
+ }
294
+ if (s_restored_ppid) {
295
+ if (kill(s_restored_ppid,0) == -1) {
296
+ if (errno == EPERM) {
297
+ return(0); // no permission, but it's still there.
298
+ }
299
+ return(1); // Dead
300
+ }
301
+ return(0); // it worked, so it's not dead
302
+ }
303
+ return(s_ppid != getppid());
304
+ }
305
+
306
+
177
307
  static void lsapi_sigpipe( int sig )
178
308
  {
179
309
  }
310
+
311
+
180
312
  static void lsapi_siguser1( int sig )
181
313
  {
182
314
  g_running = 0;
@@ -185,7 +317,7 @@ static void lsapi_siguser1( int sig )
185
317
  #ifndef sighandler_t
186
318
  typedef void (*sighandler_t)(int);
187
319
  #endif
188
-
320
+
189
321
  static void lsapi_signal(int signo, sighandler_t handler)
190
322
  {
191
323
  struct sigaction sa;
@@ -203,12 +335,12 @@ static void lsapi_signal(int signo, sighandler_t handler)
203
335
 
204
336
 
205
337
  static int s_enable_core_dump = 0;
206
- static void lsapi_enable_core_dump()
338
+ static void lsapi_enable_core_dump(void)
207
339
  {
208
340
  #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
209
341
  || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
210
342
  int mib[2];
211
- size_t len;
343
+ size_t len;
212
344
 
213
345
  len = 2;
214
346
  if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 )
@@ -219,7 +351,7 @@ static void lsapi_enable_core_dump()
219
351
  "core dump may not be available!");
220
352
  }
221
353
 
222
-
354
+
223
355
  #endif
224
356
 
225
357
  #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
@@ -230,7 +362,6 @@ static void lsapi_enable_core_dump()
230
362
  }
231
363
 
232
364
 
233
-
234
365
  static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
235
366
  char type, int len )
236
367
  {
@@ -241,6 +372,7 @@ static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader
241
372
  pHeader->m_packetLen.m_iLen = len;
242
373
  }
243
374
 
375
+
244
376
  static int lsapi_set_nblock( int fd, int nonblock )
245
377
  {
246
378
  int val = fcntl( fd, F_GETFL, 0 );
@@ -261,6 +393,7 @@ static int lsapi_set_nblock( int fd, int nonblock )
261
393
  return 0;
262
394
  }
263
395
 
396
+
264
397
  static int lsapi_close( int fd )
265
398
  {
266
399
  int ret;
@@ -273,6 +406,20 @@ static int lsapi_close( int fd )
273
406
  }
274
407
  }
275
408
 
409
+
410
+ static void lsapi_close_connection(LSAPI_Request *pReq)
411
+ {
412
+ if (pReq->m_fd == -1)
413
+ return;
414
+ lsapi_close(pReq->m_fd);
415
+ pReq->m_fd = -1;
416
+ if (s_busy_workers)
417
+ __sync_fetch_and_sub(s_busy_workers, 1);
418
+ if (s_worker_status)
419
+ __sync_lock_test_and_set(&s_worker_status->m_state, LSAPI_STATE_IDLE);
420
+ }
421
+
422
+
276
423
  static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
277
424
  {
278
425
  ssize_t ret;
@@ -285,6 +432,7 @@ static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
285
432
  }
286
433
  }
287
434
 
435
+
288
436
  /*
289
437
  static int lsapi_write( int fd, const void * pBuf, int len )
290
438
  {
@@ -307,11 +455,16 @@ static int lsapi_write( int fd, const void * pBuf, int len )
307
455
  }
308
456
  */
309
457
 
458
+
310
459
  static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
311
460
  {
312
461
  int ret;
313
462
  int left = totalLen;
314
463
  int n = count;
464
+
465
+ if (s_skip_write)
466
+ return totalLen;
467
+
315
468
  while(( left > 0 )&&g_running )
316
469
  {
317
470
  ret = writev( fd, *pVec, n );
@@ -351,6 +504,7 @@ static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
351
504
  return totalLen - left;
352
505
  }
353
506
 
507
+
354
508
  /*
355
509
  static int getTotalLen( struct iovec * pVec, int count )
356
510
  {
@@ -365,6 +519,7 @@ static int getTotalLen( struct iovec * pVec, int count )
365
519
  }
366
520
  */
367
521
 
522
+
368
523
  static inline int allocateBuf( LSAPI_Request * pReq, int size )
369
524
  {
370
525
  char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
@@ -392,6 +547,7 @@ static int allocateIovec( LSAPI_Request * pReq, int n )
392
547
  return 0;
393
548
  }
394
549
 
550
+
395
551
  static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
396
552
  {
397
553
  char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
@@ -423,11 +579,12 @@ static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktTy
423
579
  return pHeader->m_packetLen.m_iLen;
424
580
  }
425
581
 
582
+
426
583
  static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
427
584
  int *curSize, int newSize )
428
585
  {
429
586
  struct LSAPI_key_value_pair * pBuf;
430
- if ( *curSize >= newSize )
587
+ if ( *curSize >= newSize )
431
588
  return 0;
432
589
  if ( newSize > 8192 )
433
590
  return -1;
@@ -444,6 +601,7 @@ static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
444
601
 
445
602
  }
446
603
 
604
+
447
605
  static inline int isPipe( int fd )
448
606
  {
449
607
  char achPeer[128];
@@ -455,6 +613,7 @@ static inline int isPipe( int fd )
455
613
  return 1;
456
614
  }
457
615
 
616
+
458
617
  static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
459
618
  char **pBegin, char * pEnd )
460
619
  {
@@ -491,6 +650,7 @@ static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
491
650
  return 0;
492
651
  }
493
652
 
653
+
494
654
  static inline void swapIntEndian( int * pInteger )
495
655
  {
496
656
  char * p = (char *)pInteger;
@@ -501,9 +661,10 @@ static inline void swapIntEndian( int * pInteger )
501
661
  b = p[1];
502
662
  p[1] = p[2];
503
663
  p[2] = b;
504
-
664
+
505
665
  }
506
666
 
667
+
507
668
  static inline void fixEndian( LSAPI_Request * pReq )
508
669
  {
509
670
  struct lsapi_req_header *p= pReq->m_pHeader;
@@ -518,6 +679,7 @@ static inline void fixEndian( LSAPI_Request * pReq )
518
679
  swapIntEndian( &p->m_cntSpecialEnv );
519
680
  }
520
681
 
682
+
521
683
  static void fixHeaderIndexEndian( LSAPI_Request * pReq )
522
684
  {
523
685
  int i;
@@ -549,6 +711,40 @@ static void fixHeaderIndexEndian( LSAPI_Request * pReq )
549
711
  }
550
712
  }
551
713
 
714
+
715
+ static int validateHeaders( LSAPI_Request * pReq )
716
+ {
717
+ int totalLen = pReq->m_pHeader->m_httpHeaderLen;
718
+ int i;
719
+ for(i = 0; i < H_TRANSFER_ENCODING; ++i)
720
+ {
721
+ if ( pReq->m_pHeaderIndex->m_headerOff[i] )
722
+ {
723
+ if (pReq->m_pHeaderIndex->m_headerOff[i] > totalLen
724
+ || pReq->m_pHeaderIndex->m_headerLen[i]
725
+ + pReq->m_pHeaderIndex->m_headerOff[i] > totalLen)
726
+ return -1;
727
+ }
728
+ }
729
+ if (pReq->m_pHeader->m_cntUnknownHeaders > 0)
730
+ {
731
+ struct lsapi_header_offset * pCur, *pEnd;
732
+ pCur = pReq->m_pUnknownHeader;
733
+ pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
734
+ while( pCur < pEnd )
735
+ {
736
+ if (pCur->nameOff > totalLen
737
+ || pCur->nameOff + pCur->nameLen > totalLen
738
+ || pCur->valueOff > totalLen
739
+ || pCur->valueOff + pCur->valueLen > totalLen)
740
+ return -1;
741
+ ++pCur;
742
+ }
743
+ }
744
+ return 0;
745
+ }
746
+
747
+
552
748
  static uid_t s_uid = 0;
553
749
  static uid_t s_defaultUid; //web server need set this
554
750
  static gid_t s_defaultGid;
@@ -570,23 +766,23 @@ static int (*fp_lve_destroy)(struct liblve *) = NULL;
570
766
  static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL;
571
767
  static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL;
572
768
  static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
573
- static int lsapi_load_lve_lib()
769
+ static int lsapi_load_lve_lib(void)
574
770
  {
575
- s_liblve = dlopen("liblve.so.0", RTLD_LAZY);
771
+ s_liblve = dlopen("liblve.so.0", RTLD_NOW | RTLD_GLOBAL);
576
772
  if (s_liblve)
577
773
  {
578
774
  fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
579
- if (dlerror() == NULL)
775
+ if (dlerror() == NULL)
580
776
  {
581
777
  if ( !(*fp_lve_is_available)() )
582
778
  {
583
779
  int uid = getuid();
584
780
  if ( uid )
585
781
  {
586
- setreuid( s_uid, uid );
782
+ if (setreuid( s_uid, uid )) {};
587
783
  if ( !(*fp_lve_is_available)() )
588
784
  s_enable_lve = 0;
589
- setreuid( uid, s_uid );
785
+ if (setreuid( uid, s_uid )) {};
590
786
  }
591
787
  }
592
788
  }
@@ -598,11 +794,12 @@ static int lsapi_load_lve_lib()
598
794
  return (s_liblve)? 0 : -1;
599
795
  }
600
796
 
601
- static int init_lve_ex()
797
+
798
+ static int init_lve_ex(void)
602
799
  {
603
800
  int rc;
604
801
  if ( !s_liblve )
605
- return -1;
802
+ return -1;
606
803
  fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init");
607
804
  fp_lve_destroy = dlsym(s_liblve, "lve_destroy");
608
805
  fp_lve_enter = dlsym(s_liblve, "lve_enter");
@@ -610,13 +807,13 @@ static int init_lve_ex()
610
807
  if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED )
611
808
  fp_lve_jail = dlsym(s_liblve, "jail" );
612
809
 
613
- if ( s_lve == NULL )
810
+ if ( s_lve == NULL )
614
811
  {
615
812
  rc = (*fp_lve_instance_init)(NULL);
616
813
  s_lve = malloc(rc);
617
814
  }
618
815
  rc = (*fp_lve_instance_init)(s_lve);
619
- if (rc != 0)
816
+ if (rc != 0)
620
817
  {
621
818
  perror( "LSAPI: Unable to initialize LVE" );
622
819
  free( s_lve );
@@ -624,7 +821,7 @@ static int init_lve_ex()
624
821
  return -1;
625
822
  }
626
823
  return 0;
627
-
824
+
628
825
  }
629
826
 
630
827
  #endif
@@ -637,32 +834,32 @@ static int readSecret( const char * pSecretFile )
637
834
  int fd = open( pSecretFile, O_RDONLY , 0600 );
638
835
  if ( fd == -1 )
639
836
  {
640
- fprintf( stderr, "LSAPI: failed to open secret file: %s!\n", pSecretFile );
837
+ lsapi_log("LSAPI: failed to open secret file: %s!\n", pSecretFile );
641
838
  return -1;
642
839
  }
643
840
  if ( fstat( fd, &st ) == -1 )
644
841
  {
645
- fprintf( stderr, "LSAPI: failed to check state of file: %s!\n", pSecretFile );
842
+ lsapi_log("LSAPI: failed to check state of file: %s!\n", pSecretFile );
646
843
  close( fd );
647
844
  return -1;
648
845
  }
649
846
  /*
650
847
  if ( st.st_uid != s_uid )
651
848
  {
652
- fprintf( stderr, "LSAPI: file owner check failure: %s!\n", pSecretFile );
849
+ lsapi_log("LSAPI: file owner check failure: %s!\n", pSecretFile );
653
850
  close( fd );
654
851
  return -1;
655
852
  }
656
853
  */
657
854
  if ( st.st_mode & 0077 )
658
855
  {
659
- fprintf( stderr, "LSAPI: file permission check failure: %s\n", pSecretFile );
856
+ lsapi_log("LSAPI: file permission check failure: %s\n", pSecretFile );
660
857
  close( fd );
661
858
  return -1;
662
859
  }
663
- if ( read( fd, s_pSecret, 16 ) < 16 )
860
+ if ( read( fd, s_secret, 16 ) < 16 )
664
861
  {
665
- fprintf( stderr, "LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
862
+ lsapi_log("LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
666
863
  close( fd );
667
864
  return -1;
668
865
  }
@@ -670,55 +867,56 @@ static int readSecret( const char * pSecretFile )
670
867
  return 0;
671
868
  }
672
869
 
673
- static int lsapi_initSuEXEC()
674
- {
675
- int i;
676
- struct passwd * pw;
677
- pw = getpwnam( "nobody" );
678
- s_defaultUid = pw->pw_uid;
679
- s_defaultGid = pw->pw_gid;
680
- if ( s_uid == 0 )
681
- {
682
- const char * p = getenv( "LSAPI_DEFAULT_UID" );
683
- if ( p )
684
- {
685
- i = atoi( p );
686
- if ( i > 0 )
687
- s_defaultUid = i;
688
- }
689
- p = getenv( "LSAPI_DEFAULT_GID" );
690
- if ( p )
691
- {
692
- i = atoi( p );
693
- if ( i > 0 )
694
- s_defaultGid = i;
695
- }
696
- p = getenv( "LSAPI_SECRET" );
697
- if (( !p )||( readSecret(p) == -1 ))
698
- return -1;
699
- }
700
- return 0;
701
- }
702
870
 
703
- int LSAPI_is_suEXEC_Daemon()
871
+ int LSAPI_is_suEXEC_Daemon(void)
704
872
  {
705
- if (( !s_uid )&&( s_pSecret[0] ))
873
+ if (( !s_uid )&&( s_secret[0] ))
706
874
  return 1;
707
875
  else
708
876
  return 0;
709
877
  }
710
878
 
879
+
711
880
  static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
712
881
  {
713
- char achError[1024];
714
- int n = snprintf(achError, 1024, "%s:%s: %s\n", pErr1, (pErr2)?pErr2:"", strerror( errno ) );
882
+ char achError[4096];
883
+ int n = snprintf(achError, sizeof(achError), "[UID:%d][%d] %s:%s: %s\n",
884
+ getuid(), getpid(),
885
+ pErr1, (pErr2)?pErr2:"", strerror(errno));
886
+ if (n > (int)sizeof(achError))
887
+ n = sizeof(achError);
715
888
  if ( pReq )
716
889
  LSAPI_Write_Stderr_r( pReq, achError, n );
717
890
  else
718
- write( STDERR_FILENO, achError, n );
891
+ if (write( STDERR_FILENO, achError, n )) {};
719
892
  return 0;
720
893
  }
721
894
 
895
+
896
+ static int lsapi_lve_error( LSAPI_Request * pReq )
897
+ {
898
+ static const char * headers[] =
899
+ {
900
+ "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0",
901
+ "Pragma: no-cache",
902
+ "Retry-After: 60",
903
+ "Content-Type: text/html",
904
+ NULL
905
+ };
906
+ static const char achBody[] =
907
+ "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
908
+ "<HTML><HEAD>\n<TITLE>508 Resource Limit Is Reached</TITLE>\n"
909
+ "</HEAD><BODY>\n" "<H1>Resource Limit Is Reached</H1>\n"
910
+ "The website is temporarily unable to service your request as it exceeded resource limit.\n"
911
+ "Please try again later.\n"
912
+ "<HR>\n"
913
+ "</BODY></HTML>\n";
914
+
915
+ LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 );
916
+ return 0;
917
+ }
918
+
919
+
722
920
  static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
723
921
  {
724
922
  #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
@@ -729,8 +927,9 @@ static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
729
927
  ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie);
730
928
  if ( ret < 0 )
731
929
  {
732
- fprintf( stderr, "Pid (%d): enter LVE (%d) : ressult: %d !\n", getpid(), uid, ret );
930
+ //lsapi_log("enter LVE (%d) : ressult: %d !\n", uid, ret );
733
931
  LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL );
932
+ lsapi_lve_error( pReq );
734
933
  return -1;
735
934
  }
736
935
  }
@@ -739,6 +938,7 @@ static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
739
938
  return 0;
740
939
  }
741
940
 
941
+
742
942
  static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
743
943
  {
744
944
  int ret = 0;
@@ -747,8 +947,8 @@ static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
747
947
  ret = (*fp_lve_jail)( pw, error_msg );
748
948
  if ( ret < 0 )
749
949
  {
750
- fprintf( stderr, "LSAPI (%d): LVE jail(%d) ressult: %d, error: %s !\n",
751
- getpid(), uid, ret, error_msg );
950
+ lsapi_log("LSAPI: LVE jail(%d) ressult: %d, error: %s !\n",
951
+ uid, ret, error_msg );
752
952
  LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL );
753
953
  return -1;
754
954
  }
@@ -758,7 +958,7 @@ static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
758
958
 
759
959
 
760
960
  #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
761
- static int lsapi_initLVE()
961
+ static int lsapi_initLVE(void)
762
962
  {
763
963
  const char * pEnv;
764
964
  if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL )
@@ -792,7 +992,7 @@ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * p
792
992
  pw = getpwuid( uid );
793
993
  #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
794
994
  if ( s_lve )
795
- {
995
+ {
796
996
  if( lsapi_enterLVE( pReq, uid ) == -1 )
797
997
  return -1;
798
998
  if ( pw && fp_lve_jail)
@@ -809,7 +1009,7 @@ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * p
809
1009
  }
810
1010
  }
811
1011
  #endif
812
- //if ( !uid || !gid ) //do not allow root
1012
+ //if ( !uid || !gid ) //do not allow root
813
1013
  //{
814
1014
  // return -1;
815
1015
  //}
@@ -865,7 +1065,7 @@ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * p
865
1065
  return 0;
866
1066
  }
867
1067
 
868
- static int lsapi_suexec_auth( LSAPI_Request *pReq,
1068
+ static int lsapi_suexec_auth( LSAPI_Request *pReq,
869
1069
  char * pAuth, int len, char * pUgid, int ugidLen )
870
1070
  {
871
1071
  lsapi_MD5_CTX md5ctx;
@@ -873,7 +1073,7 @@ static int lsapi_suexec_auth( LSAPI_Request *pReq,
873
1073
  if ( len < 32 )
874
1074
  return -1;
875
1075
  memmove( achMD5, pAuth + 16, 16 );
876
- memmove( pAuth + 16, s_pSecret, 16 );
1076
+ memmove( pAuth + 16, s_secret, 16 );
877
1077
  lsapi_MD5Init( &md5ctx );
878
1078
  lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 );
879
1079
  lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 );
@@ -888,7 +1088,8 @@ static int lsapi_changeUGid( LSAPI_Request * pReq )
888
1088
  {
889
1089
  int uid = s_defaultUid;
890
1090
  int gid = s_defaultGid;
891
- const char * pChroot = NULL;
1091
+ const char *pStderrLog;
1092
+ const char *pChroot = NULL;
892
1093
  struct LSAPI_key_value_pair * pEnv;
893
1094
  struct LSAPI_key_value_pair * pAuth;
894
1095
  int i;
@@ -897,7 +1098,7 @@ static int lsapi_changeUGid( LSAPI_Request * pReq )
897
1098
  //with special ID 0x00
898
1099
  //authenticate the suEXEC request;
899
1100
  //first one should be MD5( nonce + lscgid secret )
900
- //remember to clear the secret after verification
1101
+ //remember to clear the secret after verification
901
1102
  //it should be set at the end of special env
902
1103
  i = pReq->m_pHeader->m_cntSpecialEnv - 1;
903
1104
  if ( i >= 0 )
@@ -913,29 +1114,29 @@ static int lsapi_changeUGid( LSAPI_Request * pReq )
913
1114
  {
914
1115
  --pReq->m_pHeader->m_cntSpecialEnv;
915
1116
  uid = *(uint32_t *)pEnv->pValue;
916
- gid = *(((uint32_t *)pEnv->pValue) + 1 );
917
- //fprintf( stderr, "LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
1117
+ gid = *(((uint32_t *)pEnv->pValue) + 1 );
1118
+ //lsapi_log("LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
918
1119
  }
919
1120
  else
920
1121
  {
921
- fprintf( stderr, "LSAPI: missing SUEXEC_UGID env, use default user!\n" );
1122
+ lsapi_log("LSAPI: missing SUEXEC_UGID env, use default user!\n" );
922
1123
  pEnv = NULL;
923
1124
  }
924
1125
  if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 )
925
1126
  {
926
- //read UID, GID from specialEnv
927
-
1127
+ //read UID, GID from specialEnv
1128
+
928
1129
  }
929
1130
  else
930
1131
  {
931
1132
  //authentication error
932
- fprintf( stderr, "LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
1133
+ lsapi_log("LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
933
1134
  uid = 0;
934
1135
  }
935
1136
  }
936
1137
  else
937
1138
  {
938
- //fprintf( stderr, "LSAPI: no SUEXEC_AUTH env, use default user!\n" );
1139
+ //lsapi_log("LSAPI: no SUEXEC_AUTH env, use default user!\n" );
939
1140
  }
940
1141
  }
941
1142
 
@@ -952,12 +1153,23 @@ static int lsapi_changeUGid( LSAPI_Request * pReq )
952
1153
  return -1;
953
1154
  }
954
1155
 
955
- s_uid = uid;
1156
+ s_uid = uid;
1157
+
1158
+ if ( pReq->m_fdListen != -1 )
1159
+ {
1160
+ close( pReq->m_fdListen );
1161
+ pReq->m_fdListen = -1;
1162
+ }
1163
+
1164
+ pStderrLog = LSAPI_GetEnv_r( pReq, "LSAPI_STDERR_LOG");
1165
+ if (pStderrLog)
1166
+ lsapi_reopen_stderr(pStderrLog);
956
1167
 
957
1168
  return 0;
958
-
1169
+
959
1170
  }
960
1171
 
1172
+
961
1173
  static int parseContentLenFromHeader(LSAPI_Request * pReq)
962
1174
  {
963
1175
  const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH );
@@ -995,12 +1207,23 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen )
995
1207
  if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
996
1208
  &pBegin, pEnd ) == -1 )
997
1209
  return -1;
998
-
1210
+ if (pReq->m_pHeader->m_scriptFileOff < 0
1211
+ || pReq->m_pHeader->m_scriptFileOff >= totalLen
1212
+ || pReq->m_pHeader->m_scriptNameOff < 0
1213
+ || pReq->m_pHeader->m_scriptNameOff >= totalLen
1214
+ || pReq->m_pHeader->m_queryStringOff < 0
1215
+ || pReq->m_pHeader->m_queryStringOff >= totalLen
1216
+ || pReq->m_pHeader->m_requestMethodOff < 0
1217
+ || pReq->m_pHeader->m_requestMethodOff >= totalLen)
1218
+ {
1219
+ lsapi_log("Bad request header - ERROR#1\n");
1220
+ return -1;
1221
+ }
999
1222
  pReq->m_pScriptFile = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
1000
1223
  pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
1001
1224
  pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
1002
1225
  pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
1003
-
1226
+
1004
1227
  pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
1005
1228
  pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
1006
1229
  pBegin += sizeof( struct lsapi_http_header_index );
@@ -1013,36 +1236,94 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen )
1013
1236
  pBegin += pReq->m_pHeader->m_httpHeaderLen;
1014
1237
  if ( pBegin != pEnd )
1015
1238
  {
1016
- fprintf( stderr, "%d: request header does match total size, total: %d, real: %ld\n", getpid(), totalLen,
1017
- pBegin - pReq->m_pReqBuf );
1239
+ lsapi_log("Request header does match total size, total: %d, "
1240
+ "real: %ld\n", totalLen, pBegin - pReq->m_pReqBuf );
1018
1241
  return -1;
1019
1242
  }
1020
1243
  if ( shouldFixEndian )
1021
1244
  {
1022
1245
  fixHeaderIndexEndian( pReq );
1023
1246
  }
1247
+
1248
+ if (validateHeaders(pReq) == -1)
1249
+ {
1250
+ lsapi_log("Bad request header - ERROR#2\n");
1251
+ return -1;
1252
+ }
1253
+
1024
1254
  pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
1025
1255
  if ( pReq->m_reqBodyLen == -2 )
1026
1256
  {
1027
1257
  parseContentLenFromHeader(pReq);
1028
1258
  }
1029
-
1259
+
1030
1260
  return 0;
1031
1261
  }
1032
1262
 
1263
+
1033
1264
  //OPTIMIZATION
1034
- static int s_accept_notify = 0;
1265
+ static char s_accept_notify = 0;
1266
+ static char s_schedule_notify = 0;
1267
+ static char s_notify_scheduled = 0;
1268
+ static char s_notified_pid = 0;
1035
1269
 
1036
- static struct lsapi_packet_header ack = {'L', 'S',
1270
+ static struct lsapi_packet_header s_ack = {'L', 'S',
1037
1271
  LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1038
- static inline int notify_req_received( int fd )
1272
+ static struct lsapi_packet_header s_conn_close_pkt = {'L', 'S',
1273
+ LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1274
+
1275
+
1276
+ static inline int send_notification_pkt( int fd, struct lsapi_packet_header *pkt )
1039
1277
  {
1040
- if ( write( fd, &ack, LSAPI_PACKET_HEADER_LEN )
1041
- < LSAPI_PACKET_HEADER_LEN )
1278
+ if ( write( fd, pkt, LSAPI_PACKET_HEADER_LEN ) < LSAPI_PACKET_HEADER_LEN )
1042
1279
  return -1;
1043
1280
  return 0;
1044
1281
  }
1045
1282
 
1283
+
1284
+ static inline int send_req_received_notification( int fd )
1285
+ {
1286
+ return send_notification_pkt(fd, &s_ack);
1287
+ }
1288
+
1289
+
1290
+ static inline int send_conn_close_notification( int fd )
1291
+ {
1292
+ return send_notification_pkt(fd, &s_conn_close_pkt);
1293
+ }
1294
+
1295
+
1296
+ //static void lsapi_sigalarm( int sig )
1297
+ //{
1298
+ // if ( s_notify_scheduled )
1299
+ // {
1300
+ // s_notify_scheduled = 0;
1301
+ // if ( g_req.m_fd != -1 )
1302
+ // write_req_received_notification( g_req.m_fd );
1303
+ // }
1304
+ //}
1305
+
1306
+
1307
+ static inline int lsapi_schedule_notify(void)
1308
+ {
1309
+ if ( !s_notify_scheduled )
1310
+ {
1311
+ alarm( 2 );
1312
+ s_notify_scheduled = 1;
1313
+ }
1314
+ return 0;
1315
+ }
1316
+
1317
+
1318
+ static inline int notify_req_received( int fd )
1319
+ {
1320
+ if ( s_schedule_notify )
1321
+ return lsapi_schedule_notify();
1322
+ return send_req_received_notification( fd );
1323
+
1324
+ }
1325
+
1326
+
1046
1327
  static inline int lsapi_notify_pid( int fd )
1047
1328
  {
1048
1329
  char achBuf[16];
@@ -1050,12 +1331,13 @@ static inline int lsapi_notify_pid( int fd )
1050
1331
  8 + LSAPI_PACKET_HEADER_LEN );
1051
1332
  memmove( &achBuf[8], "\0PID", 4 );
1052
1333
  *((int *)&achBuf[12]) = getpid();
1053
-
1334
+
1054
1335
  if ( write( fd, achBuf, 16 ) < 16 )
1055
1336
  return -1;
1056
1337
  return 0;
1057
1338
  }
1058
1339
 
1340
+
1059
1341
  static char s_conn_key_packet[16];
1060
1342
  static inline int init_conn_key( int fd )
1061
1343
  {
@@ -1074,10 +1356,11 @@ static inline int init_conn_key( int fd )
1074
1356
  < LSAPI_PACKET_HEADER_LEN+8 )
1075
1357
  return -1;
1076
1358
  return 0;
1077
-
1359
+
1078
1360
 
1079
1361
  }
1080
1362
 
1363
+
1081
1364
  static int readReq( LSAPI_Request * pReq )
1082
1365
  {
1083
1366
  int len;
@@ -1102,12 +1385,12 @@ static int readReq( LSAPI_Request * pReq )
1102
1385
  packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
1103
1386
  if ( packetLen < 0 )
1104
1387
  {
1105
- fprintf( stderr, "%d: packetLen < 0\n", getpid() );
1388
+ lsapi_log("packetLen < 0\n");
1106
1389
  return -1;
1107
1390
  }
1108
1391
  if ( packetLen > LSAPI_MAX_HEADER_LEN )
1109
1392
  {
1110
- fprintf( stderr, "%d: packetLen > %d\n", getpid(), LSAPI_MAX_HEADER_LEN );
1393
+ lsapi_log("packetLen > %d\n", LSAPI_MAX_HEADER_LEN );
1111
1394
  return -1;
1112
1395
  }
1113
1396
 
@@ -1125,59 +1408,80 @@ static int readReq( LSAPI_Request * pReq )
1125
1408
  }
1126
1409
  if ( parseRequest( pReq, packetLen ) < 0 )
1127
1410
  {
1128
- fprintf( stderr, "%d: parseRequest error\n", getpid() );
1411
+ lsapi_log("ParseRequest error\n");
1129
1412
  return -1;
1130
1413
  }
1414
+
1415
+ pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
1416
+
1131
1417
  if ( !s_uid )
1418
+ {
1132
1419
  if ( lsapi_changeUGid( pReq ) )
1133
1420
  return -1;
1421
+ memset(s_secret, 0, sizeof(s_secret));
1422
+ }
1134
1423
  pReq->m_bufProcessed = packetLen;
1135
- pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
1136
1424
 
1137
1425
  //OPTIMIZATION
1138
- if ( !s_accept_notify )
1426
+ if ( !s_accept_notify && !s_notified_pid )
1139
1427
  return notify_req_received( pReq->m_fd );
1140
1428
  else
1429
+ {
1430
+ s_notified_pid = 0;
1141
1431
  return 0;
1432
+ }
1142
1433
  }
1143
1434
 
1144
1435
 
1145
-
1146
1436
  int LSAPI_Init(void)
1147
1437
  {
1148
1438
  if ( !g_inited )
1149
1439
  {
1150
1440
  s_uid = geteuid();
1151
- s_pSecret[0] = 0;
1441
+ s_secret[0] = 0;
1152
1442
  lsapi_signal(SIGPIPE, lsapi_sigpipe);
1153
1443
  lsapi_signal(SIGUSR1, lsapi_siguser1);
1154
1444
 
1155
1445
  #if defined(SIGXFSZ) && defined(SIG_IGN)
1156
1446
  signal(SIGXFSZ, SIG_IGN);
1157
1447
  #endif
1158
- /* let STDOUT function as STDERR,
1448
+ /* let STDOUT function as STDERR,
1159
1449
  just in case writing to STDOUT directly */
1160
- dup2( 2, 1 );
1450
+ dup2( 2, 1 );
1161
1451
  if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 )
1162
1452
  return -1;
1163
1453
  g_inited = 1;
1164
1454
  s_ppid = getppid();
1455
+ void *pthread_lib = dlopen("libpthread.so", RTLD_LAZY);
1456
+ if (pthread_lib)
1457
+ pthread_atfork_func = dlsym(pthread_lib, "pthread_atfork");
1458
+
1165
1459
  }
1166
1460
  return 0;
1167
1461
  }
1168
1462
 
1463
+
1169
1464
  void LSAPI_Stop(void)
1170
1465
  {
1171
1466
  g_running = 0;
1172
1467
  }
1173
1468
 
1469
+
1174
1470
  int LSAPI_IsRunning(void)
1175
1471
  {
1176
1472
  return g_running;
1177
1473
  }
1178
1474
 
1475
+
1476
+ void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb)
1477
+ {
1478
+ s_proc_group_timer_cb = cb;
1479
+ }
1480
+
1481
+
1179
1482
  int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
1180
1483
  {
1484
+ int newfd;
1181
1485
  if ( !pReq )
1182
1486
  return -1;
1183
1487
  memset( pReq, 0, sizeof( LSAPI_Request ) );
@@ -1191,7 +1495,14 @@ int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
1191
1495
  pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
1192
1496
  if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
1193
1497
  return -1;
1194
-
1498
+
1499
+ if ( fd == STDIN_FILENO )
1500
+ {
1501
+ fd = dup( fd );
1502
+ newfd = open( "/dev/null", O_RDWR );
1503
+ dup2( newfd, STDIN_FILENO );
1504
+ }
1505
+
1195
1506
  if ( isPipe( fd ) )
1196
1507
  {
1197
1508
  pReq->m_fdListen = -1;
@@ -1206,24 +1517,25 @@ int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
1206
1517
  return 0;
1207
1518
  }
1208
1519
 
1520
+
1209
1521
  int LSAPI_Is_Listen( void )
1210
1522
  {
1211
1523
  return LSAPI_Is_Listen_r( &g_req );
1212
1524
  }
1213
1525
 
1526
+
1214
1527
  int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
1215
1528
  {
1216
1529
  return pReq->m_fdListen != -1;
1217
1530
  }
1218
1531
 
1219
1532
 
1220
-
1221
1533
  int LSAPI_Accept_r( LSAPI_Request * pReq )
1222
1534
  {
1223
1535
  char achPeer[128];
1224
1536
  socklen_t len;
1225
1537
  int nodelay = 1;
1226
-
1538
+
1227
1539
  if ( !pReq )
1228
1540
  return -1;
1229
1541
  if ( LSAPI_Finish_r( pReq ) == -1 )
@@ -1247,9 +1559,14 @@ int LSAPI_Accept_r( LSAPI_Request * pReq )
1247
1559
  }
1248
1560
  else
1249
1561
  {
1562
+ if (s_worker_status)
1563
+ __sync_lock_test_and_set(&s_worker_status->m_state,
1564
+ LSAPI_STATE_CONNECTED);
1565
+ if (s_busy_workers)
1566
+ __sync_fetch_and_add(s_busy_workers, 1);
1250
1567
  lsapi_set_nblock( pReq->m_fd , 0 );
1251
1568
  if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
1252
- {
1569
+ {
1253
1570
  setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
1254
1571
  (char *)&nodelay, sizeof(nodelay));
1255
1572
  }
@@ -1266,15 +1583,19 @@ int LSAPI_Accept_r( LSAPI_Request * pReq )
1266
1583
  if ( !readReq( pReq ) )
1267
1584
  break;
1268
1585
  //abort();
1269
- lsapi_close( pReq->m_fd );
1270
- pReq->m_fd = -1;
1586
+ lsapi_close_connection(pReq);
1271
1587
  LSAPI_Reset_r( pReq );
1272
1588
  }
1273
1589
  return 0;
1274
1590
  }
1275
1591
 
1276
- static struct lsapi_packet_header finish = {'L', 'S',
1277
- LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1592
+
1593
+ static struct lsapi_packet_header finish_close[2] =
1594
+ {
1595
+ {'L', 'S', LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} },
1596
+ {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }
1597
+ };
1598
+
1278
1599
 
1279
1600
  int LSAPI_Finish_r( LSAPI_Request * pReq )
1280
1601
  {
@@ -1293,8 +1614,8 @@ int LSAPI_Finish_r( LSAPI_Request * pReq )
1293
1614
  {
1294
1615
  Flush_RespBuf_r( pReq );
1295
1616
  }
1296
-
1297
- pReq->m_pIovecCur->iov_base = (void *)&finish;
1617
+
1618
+ pReq->m_pIovecCur->iov_base = (void *)finish_close;
1298
1619
  pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
1299
1620
  pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
1300
1621
  ++pReq->m_pIovecCur;
@@ -1306,27 +1627,62 @@ int LSAPI_Finish_r( LSAPI_Request * pReq )
1306
1627
  }
1307
1628
 
1308
1629
 
1309
- void LSAPI_Reset_r( LSAPI_Request * pReq )
1310
- {
1311
- pReq->m_pRespBufPos = pReq->m_pRespBuf;
1312
- pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1313
- pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf;
1314
-
1315
- memset( &pReq->m_pHeaderIndex, 0,
1316
- (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
1317
- }
1318
-
1319
-
1320
- int LSAPI_Release_r( LSAPI_Request * pReq )
1630
+ int LSAPI_End_Response_r(LSAPI_Request * pReq)
1321
1631
  {
1322
- if ( pReq->m_pReqBuf )
1632
+ if (!pReq)
1633
+ return -1;
1634
+ if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
1635
+ return 0;
1636
+ if (pReq->m_reqState)
1637
+ {
1638
+ if ( pReq->m_fd != -1 )
1639
+ {
1640
+ if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1641
+ {
1642
+ if ( pReq->m_pRespHeaderBufPos <= pReq->m_pRespHeaderBuf )
1643
+ return 0;
1644
+
1645
+ LSAPI_FinalizeRespHeaders_r( pReq );
1646
+ }
1647
+ if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1648
+ {
1649
+ Flush_RespBuf_r( pReq );
1650
+ }
1651
+
1652
+ pReq->m_pIovecCur->iov_base = (void *)finish_close;
1653
+ pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN << 1;
1654
+ pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN << 1;
1655
+ ++pReq->m_pIovecCur;
1656
+ LSAPI_Flush_r( pReq );
1657
+ lsapi_close_connection(pReq);
1658
+ }
1659
+ pReq->m_reqState |= LSAPI_ST_BACKGROUND;
1660
+ }
1661
+ return 0;
1662
+ }
1663
+
1664
+
1665
+ void LSAPI_Reset_r( LSAPI_Request * pReq )
1666
+ {
1667
+ pReq->m_pRespBufPos = pReq->m_pRespBuf;
1668
+ pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1669
+ pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf;
1670
+
1671
+ memset( &pReq->m_pHeaderIndex, 0,
1672
+ (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
1673
+ }
1674
+
1675
+
1676
+ int LSAPI_Release_r( LSAPI_Request * pReq )
1677
+ {
1678
+ if ( pReq->m_pReqBuf )
1323
1679
  free( pReq->m_pReqBuf );
1324
1680
  if ( pReq->m_pSpecialEnvList )
1325
1681
  free( pReq->m_pSpecialEnvList );
1326
1682
  if ( pReq->m_pEnvList )
1327
1683
  free( pReq->m_pEnvList );
1328
1684
  if ( pReq->m_pRespHeaderBuf )
1329
- free( pReq->m_pRespHeaderBuf );
1685
+ free( pReq->m_pRespHeaderBuf );
1330
1686
  return 0;
1331
1687
  }
1332
1688
 
@@ -1339,13 +1695,16 @@ char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
1339
1695
  off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
1340
1696
  if ( !off )
1341
1697
  return NULL;
1342
- if ( *(pReq->m_pHttpHeader + off +
1343
- pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
1344
- *( pReq->m_pHttpHeader + off +
1345
- pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
1698
+ if ( *(pReq->m_pHttpHeader + off
1699
+ + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
1700
+ {
1701
+ *( pReq->m_pHttpHeader + off
1702
+ + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
1703
+ }
1346
1704
  return pReq->m_pHttpHeader + off;
1347
1705
  }
1348
1706
 
1707
+
1349
1708
  static int readBodyToReqBuf( LSAPI_Request * pReq )
1350
1709
  {
1351
1710
  off_t bodyLeft;
@@ -1360,7 +1719,7 @@ static int readBodyToReqBuf( LSAPI_Request * pReq )
1360
1719
  return -1;
1361
1720
  if ( len > bodyLeft )
1362
1721
  len = bodyLeft;
1363
-
1722
+
1364
1723
  len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
1365
1724
  if ( len > 0 )
1366
1725
  pReq->m_bufRead += len;
@@ -1382,7 +1741,6 @@ int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
1382
1741
  }
1383
1742
 
1384
1743
 
1385
-
1386
1744
  int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF )
1387
1745
  {
1388
1746
  ssize_t len;
@@ -1391,12 +1749,12 @@ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, in
1391
1749
  char * pBufCur = pBuf;
1392
1750
  char * pCur;
1393
1751
  char * p;
1394
- if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF )
1752
+ if (!pReq || pReq->m_fd == -1 || !pBuf || !getLF)
1395
1753
  return -1;
1396
1754
  *getLF = 0;
1397
1755
  while( (left = pBufEnd - pBufCur ) > 0 )
1398
1756
  {
1399
-
1757
+
1400
1758
  len = pReq->m_bufRead - pReq->m_bufProcessed;
1401
1759
  if ( len <= 0 )
1402
1760
  {
@@ -1417,7 +1775,7 @@ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, in
1417
1775
  pReq->m_bufProcessed += len;
1418
1776
 
1419
1777
  pReq->m_reqBodyRead += len;
1420
-
1778
+
1421
1779
  if ( p )
1422
1780
  {
1423
1781
  *getLF = 1;
@@ -1425,7 +1783,7 @@ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, in
1425
1783
  }
1426
1784
  }
1427
1785
  *pBufCur = 0;
1428
-
1786
+
1429
1787
  return pBufCur - pBuf;
1430
1788
  }
1431
1789
 
@@ -1435,21 +1793,21 @@ ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
1435
1793
  ssize_t len;
1436
1794
  off_t total;
1437
1795
  /* char *pOldBuf = pBuf; */
1438
- if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 ))
1796
+ if (!pReq || pReq->m_fd == -1 || !pBuf || (ssize_t)bufLen < 0)
1439
1797
  return -1;
1440
1798
 
1441
1799
  total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1442
-
1800
+
1443
1801
  if ( total <= 0 )
1444
1802
  return 0;
1445
- if ( total < bufLen )
1803
+ if ( total < (ssize_t)bufLen )
1446
1804
  bufLen = total;
1447
1805
 
1448
1806
  total = 0;
1449
1807
  len = pReq->m_bufRead - pReq->m_bufProcessed;
1450
1808
  if ( len > 0 )
1451
1809
  {
1452
- if ( len > bufLen )
1810
+ if ( len > (ssize_t)bufLen )
1453
1811
  len = bufLen;
1454
1812
  memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
1455
1813
  pReq->m_bufProcessed += len;
@@ -1475,7 +1833,7 @@ ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
1475
1833
  }
1476
1834
  pReq->m_reqBodyRead += total;
1477
1835
  return total;
1478
-
1836
+
1479
1837
  }
1480
1838
 
1481
1839
 
@@ -1488,8 +1846,12 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1488
1846
  ssize_t toWrite;
1489
1847
  ssize_t packetLen;
1490
1848
  int skip = 0;
1491
-
1492
- if ( !pReq || !pBuf || (pReq->m_fd == -1) )
1849
+
1850
+ if (!pReq || !pBuf)
1851
+ return -1;
1852
+ if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
1853
+ return len;
1854
+ if (pReq->m_fd == -1)
1493
1855
  return -1;
1494
1856
  if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1495
1857
  {
@@ -1507,19 +1869,19 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1507
1869
  }
1508
1870
  pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1509
1871
 
1510
- if ( (len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos )
1872
+ if ( ((ssize_t)len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos )
1511
1873
  {
1512
1874
  memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip );
1513
1875
  pReq->m_pRespBufPos += len - skip;
1514
1876
  return len;
1515
1877
  }
1516
-
1517
-
1878
+
1879
+
1518
1880
  pHeader = pReq->m_respPktHeader;
1519
1881
  p = pBuf + skip;
1520
1882
  pEnd = pBuf + len;
1521
1883
  bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
1522
-
1884
+
1523
1885
  while( ( toWrite = pEnd - p ) > 0 )
1524
1886
  {
1525
1887
  packetLen = toWrite + bufLen;
@@ -1528,7 +1890,7 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1528
1890
  packetLen = LSAPI_MAX_DATA_PACKET_LEN;
1529
1891
  toWrite = packetLen - bufLen;
1530
1892
  }
1531
-
1893
+
1532
1894
  lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1533
1895
  packetLen + LSAPI_PACKET_HEADER_LEN );
1534
1896
  pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
@@ -1542,7 +1904,7 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1542
1904
  pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
1543
1905
  pReq->m_pIovecCur->iov_len = bufLen;
1544
1906
  pReq->m_pRespBufPos = pReq->m_pRespBuf;
1545
- ++pReq->m_pIovecCur;
1907
+ ++pReq->m_pIovecCur;
1546
1908
  bufLen = 0;
1547
1909
  }
1548
1910
 
@@ -1564,7 +1926,8 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1564
1926
  return p - pBuf;
1565
1927
  }
1566
1928
 
1567
- #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__)
1929
+
1930
+ #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__)
1568
1931
  ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1569
1932
  {
1570
1933
  ssize_t ret;
@@ -1579,6 +1942,7 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1579
1942
  }
1580
1943
  #endif
1581
1944
 
1945
+
1582
1946
  #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
1583
1947
  ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1584
1948
  {
@@ -1593,7 +1957,8 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1593
1957
  return ret;
1594
1958
  }
1595
1959
  #endif
1596
-
1960
+
1961
+
1597
1962
  #if defined(sun) || defined(__sun)
1598
1963
  #include <sys/sendfile.h>
1599
1964
  ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
@@ -1608,7 +1973,7 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
1608
1973
  ++n;
1609
1974
 
1610
1975
  size_t written;
1611
- ssize_t ret = ::sendfilev( fdOut, vec, n, &written );
1976
+ ssize_t ret = sendfilev( fdOut, vec, n, &written );
1612
1977
  if (( !ret )||( errno == EAGAIN ))
1613
1978
  ret = written;
1614
1979
  if ( ret > 0 )
@@ -1617,11 +1982,14 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
1617
1982
  }
1618
1983
  #endif
1619
1984
 
1985
+
1620
1986
  #if defined(linux) || defined(__linux) || defined(__linux__) || \
1621
1987
  defined(__gnu_linux__)
1622
1988
  #include <sys/sendfile.h>
1623
1989
  #define gsendfile sendfile
1624
1990
  #endif
1991
+
1992
+
1625
1993
  #if defined(HPUX)
1626
1994
  ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
1627
1995
  {
@@ -1629,6 +1997,7 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
1629
1997
  }
1630
1998
  #endif
1631
1999
 
2000
+
1632
2001
  ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size )
1633
2002
  {
1634
2003
  struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
@@ -1639,16 +2008,16 @@ ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t siz
1639
2008
  LSAPI_FinalizeRespHeaders_r( pReq );
1640
2009
  }
1641
2010
  pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1642
-
2011
+
1643
2012
  LSAPI_Flush_r(pReq);
1644
-
2013
+
1645
2014
  lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1646
2015
  size + LSAPI_PACKET_HEADER_LEN );
1647
-
2016
+
1648
2017
 
1649
2018
  if (write(pReq->m_fd, (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN)
1650
2019
  return -1;
1651
-
2020
+
1652
2021
  return gsendfile( pReq->m_fd, fdIn, off, size );
1653
2022
  }
1654
2023
 
@@ -1671,14 +2040,12 @@ void Flush_RespBuf_r( LSAPI_Request * pReq )
1671
2040
  pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
1672
2041
  pReq->m_pIovecCur->iov_len = bufLen;
1673
2042
  pReq->m_pRespBufPos = pReq->m_pRespBuf;
1674
- ++pReq->m_pIovecCur;
2043
+ ++pReq->m_pIovecCur;
1675
2044
  bufLen = 0;
1676
2045
  }
1677
2046
  }
1678
2047
 
1679
2048
 
1680
-
1681
-
1682
2049
  int LSAPI_Flush_r( LSAPI_Request * pReq )
1683
2050
  {
1684
2051
  int ret = 0;
@@ -1703,17 +2070,16 @@ int LSAPI_Flush_r( LSAPI_Request * pReq )
1703
2070
  {
1704
2071
  Flush_RespBuf_r( pReq );
1705
2072
  }
1706
-
2073
+
1707
2074
  n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
1708
2075
  if ( n > 0 )
1709
2076
  {
1710
-
2077
+
1711
2078
  ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
1712
2079
  n, pReq->m_totalLen );
1713
2080
  if ( ret < pReq->m_totalLen )
1714
2081
  {
1715
- lsapi_close( pReq->m_fd );
1716
- pReq->m_fd = -1;
2082
+ lsapi_close_connection(pReq);
1717
2083
  ret = -1;
1718
2084
  }
1719
2085
  pReq->m_totalLen = 0;
@@ -1733,16 +2099,16 @@ ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t le
1733
2099
  int ret;
1734
2100
  struct iovec iov[2];
1735
2101
  struct iovec *pIov;
1736
-
2102
+
1737
2103
  if ( !pReq )
1738
2104
  return -1;
1739
- if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen ))
2105
+ if (s_stderr_log_path || pReq->m_fd == -1 || pReq->m_fd == pReq->m_fdListen)
1740
2106
  return write( 2, pBuf, len );
1741
2107
  if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1742
2108
  {
1743
2109
  LSAPI_Flush_r( pReq );
1744
2110
  }
1745
-
2111
+
1746
2112
  p = pBuf;
1747
2113
  pEnd = pBuf + len;
1748
2114
 
@@ -1768,23 +2134,32 @@ ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t le
1768
2134
  2, totalLen );
1769
2135
  if ( ret < totalLen )
1770
2136
  {
1771
- lsapi_close( pReq->m_fd );
1772
- pReq->m_fd = -1;
2137
+ lsapi_close_connection(pReq);
1773
2138
  ret = -1;
1774
2139
  }
1775
2140
  }
1776
2141
  return p - pBuf;
1777
2142
  }
1778
2143
 
2144
+
1779
2145
  static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
1780
2146
  {
1781
2147
  int i;
2148
+ char * pValue;
1782
2149
  for( i = 0; i < H_TRANSFER_ENCODING; ++i )
1783
2150
  {
1784
2151
  if ( pReq->m_pHeaderIndex->m_headerOff[i] )
1785
2152
  {
1786
2153
  if ( strcmp( name, CGI_HEADERS[i] ) == 0 )
1787
- return pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
2154
+ {
2155
+ pValue = pReq->m_pHttpHeader
2156
+ + pReq->m_pHeaderIndex->m_headerOff[i];
2157
+ if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0')
2158
+ {
2159
+ *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0';
2160
+ }
2161
+ return pValue;
2162
+ }
1788
2163
  }
1789
2164
  }
1790
2165
  if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
@@ -1811,7 +2186,15 @@ static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
1811
2186
  ++p; ++pKey;
1812
2187
  }
1813
2188
  if (( pKey == pKeyEnd )&& (!*p ))
1814
- return pReq->m_pHttpHeader + pCur->valueOff;
2189
+ {
2190
+ pValue = pReq->m_pHttpHeader + pCur->valueOff;
2191
+
2192
+ if ( *(pValue + pCur->valueLen) != '\0')
2193
+ {
2194
+ *(pValue + pCur->valueLen) = '\0';
2195
+ }
2196
+ return pValue;
2197
+ }
1815
2198
  ++pCur;
1816
2199
  }
1817
2200
  }
@@ -1838,6 +2221,7 @@ char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
1838
2221
  return NULL;
1839
2222
  }
1840
2223
 
2224
+
1841
2225
  struct _headerInfo
1842
2226
  {
1843
2227
  const char * _name;
@@ -1846,12 +2230,14 @@ struct _headerInfo
1846
2230
  int _valueLen;
1847
2231
  };
1848
2232
 
2233
+
1849
2234
  int compareValueLocation(const void * v1, const void *v2 )
1850
2235
  {
1851
2236
  return ((const struct _headerInfo *)v1)->_value -
1852
- ((const struct _headerInfo *)v2)->_value;
2237
+ ((const struct _headerInfo *)v2)->_value;
1853
2238
  }
1854
2239
 
2240
+
1855
2241
  int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1856
2242
  LSAPI_CB_EnvHandler fn, void * arg )
1857
2243
  {
@@ -1861,9 +2247,13 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1861
2247
  int ret;
1862
2248
  int count = 0;
1863
2249
  struct _headerInfo headers[512];
2250
+
1864
2251
  if ( !pReq || !fn )
1865
2252
  return -1;
1866
-
2253
+
2254
+ if ( !pReq->m_pHeaderIndex )
2255
+ return 0;
2256
+
1867
2257
  for( i = 0; i < H_TRANSFER_ENCODING; ++i )
1868
2258
  {
1869
2259
  if ( pReq->m_pHeaderIndex->m_headerOff[i] )
@@ -1876,7 +2266,7 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1876
2266
  headers[count]._value = pValue;
1877
2267
  headers[count]._valueLen = len;
1878
2268
  ++count;
1879
-
2269
+
1880
2270
  //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
1881
2271
  // pValue, len, arg );
1882
2272
  //if ( ret <= 0 )
@@ -1894,6 +2284,7 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1894
2284
  {
1895
2285
  pKey = pReq->m_pHttpHeader + pCur->nameOff;
1896
2286
  keyLen = pCur->nameLen;
2287
+ *(pKey + keyLen ) = 0;
1897
2288
 
1898
2289
  pValue = pReq->m_pHttpHeader + pCur->valueOff;
1899
2290
  *(pValue + pCur->valueLen ) = 0;
@@ -1904,7 +2295,7 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1904
2295
  ++count;
1905
2296
  if ( count == 512 )
1906
2297
  break;
1907
- //ret = (*fn)( pKey, keyLen,
2298
+ //ret = (*fn)( pKey, keyLen,
1908
2299
  // pValue, pCur->valueLen, arg );
1909
2300
  //if ( ret <= 0 )
1910
2301
  // return ret;
@@ -1914,13 +2305,12 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1914
2305
  qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation );
1915
2306
  for( i = 0; i < count; ++i )
1916
2307
  {
1917
- ret = (*fn)( headers[i]._name, headers[i]._nameLen,
2308
+ ret = (*fn)( headers[i]._name, headers[i]._nameLen,
1918
2309
  headers[i]._value, headers[i]._valueLen, arg );
1919
2310
  if ( ret <= 0 )
1920
2311
  return ret;
1921
2312
  }
1922
2313
  return count;
1923
-
1924
2314
  }
1925
2315
 
1926
2316
 
@@ -1981,7 +2371,7 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
1981
2371
 
1982
2372
  pValue = pReq->m_pHttpHeader + pCur->valueOff;
1983
2373
  *(pValue + pCur->valueLen ) = 0;
1984
- ret = (*fn)( achHeaderName, keyLen,
2374
+ ret = (*fn)( achHeaderName, keyLen,
1985
2375
  pValue, pCur->valueLen, arg );
1986
2376
  if ( ret <= 0 )
1987
2377
  return ret;
@@ -1989,9 +2379,9 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
1989
2379
  }
1990
2380
  }
1991
2381
  return count + pReq->m_pHeader->m_cntUnknownHeaders;
1992
-
1993
2382
  }
1994
2383
 
2384
+
1995
2385
  static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
1996
2386
  int n, LSAPI_CB_EnvHandler fn, void * arg )
1997
2387
  {
@@ -2011,7 +2401,6 @@ static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
2011
2401
  }
2012
2402
 
2013
2403
 
2014
-
2015
2404
  int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
2016
2405
  LSAPI_CB_EnvHandler fn, void * arg )
2017
2406
  {
@@ -2026,7 +2415,6 @@ int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
2026
2415
  }
2027
2416
 
2028
2417
 
2029
-
2030
2418
  int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
2031
2419
  LSAPI_CB_EnvHandler fn, void * arg )
2032
2420
  {
@@ -2043,7 +2431,6 @@ int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
2043
2431
  }
2044
2432
 
2045
2433
 
2046
-
2047
2434
  int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
2048
2435
  {
2049
2436
  if ( !pReq || !pReq->m_pIovec )
@@ -2058,7 +2445,7 @@ int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
2058
2445
  pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
2059
2446
  ++pReq->m_pIovecCur;
2060
2447
  }
2061
-
2448
+
2062
2449
  pReq->m_pIovec->iov_len = sizeof( struct lsapi_resp_header)
2063
2450
  + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
2064
2451
  pReq->m_totalLen += pReq->m_pIovec->iov_len;
@@ -2071,11 +2458,11 @@ int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
2071
2458
  }
2072
2459
 
2073
2460
 
2074
- int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2461
+ int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2075
2462
  const char * pHeaderValue )
2076
2463
  {
2077
2464
  int nameLen, valLen, len;
2078
- if ( !pReq || !pHeaderName || !pHeaderValue )
2465
+ if ( !pReq || !pHeaderName || !pHeaderValue )
2079
2466
  return -1;
2080
2467
  if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2081
2468
  return -1;
@@ -2127,7 +2514,6 @@ int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2127
2514
  }
2128
2515
 
2129
2516
 
2130
-
2131
2517
  int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len )
2132
2518
  {
2133
2519
  if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX )
@@ -2208,9 +2594,9 @@ int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
2208
2594
  close(fd);
2209
2595
  errno = ret;
2210
2596
  return -1;
2211
-
2212
2597
  }
2213
2598
 
2599
+
2214
2600
  int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2215
2601
  {
2216
2602
  char achAddr[256];
@@ -2219,14 +2605,15 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2219
2605
  struct addrinfo *res, hints;
2220
2606
  int doAddrInfo = 0;
2221
2607
  int port;
2222
-
2608
+
2223
2609
  if ( !pBind )
2224
2610
  return -1;
2225
2611
 
2226
2612
  while( isspace( *pBind ) )
2227
2613
  ++pBind;
2228
2614
 
2229
- strncpy( achAddr, pBind, 256 );
2615
+ strncpy(achAddr, pBind, 255);
2616
+ achAddr[255] = 0;
2230
2617
 
2231
2618
  switch( *p )
2232
2619
  {
@@ -2243,7 +2630,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2243
2630
  if ( !pEnd )
2244
2631
  return -1;
2245
2632
  *pEnd++ = 0;
2246
-
2633
+
2247
2634
  if ( *p == '*' )
2248
2635
  {
2249
2636
  strcpy( achAddr, "::" );
@@ -2258,7 +2645,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2258
2645
  if ( !pEnd )
2259
2646
  return -1;
2260
2647
  *pEnd++ = 0;
2261
-
2648
+
2262
2649
  doAddrInfo = 0;
2263
2650
  if ( *p == '*' )
2264
2651
  {
@@ -2278,7 +2665,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2278
2665
  }
2279
2666
  if ( *pEnd == ':' )
2280
2667
  ++pEnd;
2281
-
2668
+
2282
2669
  port = atoi( pEnd );
2283
2670
  if (( port <= 0 )||( port > 65535 ))
2284
2671
  return -1;
@@ -2299,15 +2686,16 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2299
2686
  memcpy(pAddr, res->ai_addr, res->ai_addrlen);
2300
2687
  freeaddrinfo(res);
2301
2688
  }
2302
-
2689
+
2303
2690
  if ( pAddr->sa_family == AF_INET )
2304
2691
  ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
2305
2692
  else
2306
2693
  ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
2307
2694
  return 0;
2308
-
2695
+
2309
2696
  }
2310
2697
 
2698
+
2311
2699
  int LSAPI_CreateListenSock( const char * pBind, int backlog )
2312
2700
  {
2313
2701
  char serverAddr[128];
@@ -2321,25 +2709,8 @@ int LSAPI_CreateListenSock( const char * pBind, int backlog )
2321
2709
  return fd;
2322
2710
  }
2323
2711
 
2324
- static fn_select_t g_fnSelect = select;
2325
-
2326
- typedef struct _lsapi_child_status
2327
- {
2328
- int m_pid;
2329
- long m_tmStart;
2330
-
2331
- volatile short m_iKillSent;
2332
- volatile short m_inProcess;
2333
- volatile int m_iReqCounter;
2334
-
2335
- volatile long m_tmWaitBegin;
2336
- volatile long m_tmReqBegin;
2337
- volatile long m_tmLastCheckPoint;
2338
- }
2339
- lsapi_child_status;
2340
-
2341
- static lsapi_child_status * s_pChildStatus = NULL;
2342
2712
 
2713
+ static fn_select_t g_fnSelect = select;
2343
2714
  typedef struct _lsapi_prefork_server
2344
2715
  {
2345
2716
  int m_fd;
@@ -2351,16 +2722,17 @@ typedef struct _lsapi_prefork_server
2351
2722
  int m_iChildrenMaxIdleTime;
2352
2723
  int m_iMaxReqProcessTime;
2353
2724
  int m_iAvoidFork;
2354
-
2725
+
2355
2726
  lsapi_child_status * m_pChildrenStatus;
2356
-
2357
- }lsapi_prefork_server;
2727
+ lsapi_child_status * m_pChildrenStatusCur;
2728
+ lsapi_child_status * m_pChildrenStatusEnd;
2358
2729
 
2730
+ }lsapi_prefork_server;
2359
2731
  static lsapi_prefork_server * g_prefork_server = NULL;
2360
2732
 
2733
+
2361
2734
  int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
2362
2735
  {
2363
- int pid;
2364
2736
  if ( g_prefork_server )
2365
2737
  return 0;
2366
2738
  if ( max_children <= 1 )
@@ -2368,7 +2740,9 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
2368
2740
  if ( max_children >= 10000)
2369
2741
  max_children = 10000;
2370
2742
 
2371
-
2743
+ if (s_max_busy_workers == 0)
2744
+ s_max_busy_workers = max_children / 2 + 1;
2745
+
2372
2746
  g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
2373
2747
  if ( !g_prefork_server )
2374
2748
  return -1;
@@ -2378,20 +2752,27 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
2378
2752
  g_fnSelect = fp;
2379
2753
 
2380
2754
  s_ppid = getppid();
2381
- pid = getpid();
2382
- setpgid( pid, pid );
2755
+ s_pid = getpid();
2756
+ setpgid( s_pid, s_pid );
2757
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
2758
+ s_total_pages = sysconf(_SC_PHYS_PAGES);
2759
+ #endif
2383
2760
  g_prefork_server->m_iAvoidFork = avoidFork;
2384
2761
  g_prefork_server->m_iMaxChildren = max_children;
2385
-
2762
+
2386
2763
  g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
2387
2764
  g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
2388
2765
  if ( g_prefork_server->m_iMaxIdleChildren == 0 )
2389
2766
  g_prefork_server->m_iMaxIdleChildren = 1;
2390
2767
  g_prefork_server->m_iChildrenMaxIdleTime = 300;
2391
- g_prefork_server->m_iMaxReqProcessTime = 300;
2392
- return 0;
2768
+ g_prefork_server->m_iMaxReqProcessTime = 3600;
2769
+
2770
+ setsid();
2771
+
2772
+ return 0;
2393
2773
  }
2394
2774
 
2775
+
2395
2776
  void LSAPI_Set_Server_fd( int fd )
2396
2777
  {
2397
2778
  if( g_prefork_server )
@@ -2425,12 +2806,8 @@ static int lsapi_accept( int fdListen )
2425
2806
  }
2426
2807
 
2427
2808
 
2428
-
2429
-
2430
- static int s_req_processed = 0;
2431
- static int s_max_reqs = 10000;
2809
+ static unsigned int s_max_reqs = UINT_MAX;
2432
2810
  static int s_max_idle_secs = 300;
2433
-
2434
2811
  static int s_stop;
2435
2812
 
2436
2813
  static void lsapi_cleanup(int signal)
@@ -2438,25 +2815,57 @@ static void lsapi_cleanup(int signal)
2438
2815
  s_stop = signal;
2439
2816
  }
2440
2817
 
2818
+
2441
2819
  static lsapi_child_status * find_child_status( int pid )
2442
2820
  {
2443
2821
  lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2444
- lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
2822
+ lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2445
2823
  while( pStatus < pEnd )
2446
2824
  {
2447
2825
  if ( pStatus->m_pid == pid )
2826
+ {
2827
+ if (pid == 0)
2828
+ {
2829
+ memset(pStatus, 0, sizeof( *pStatus ) );
2830
+ pStatus->m_pid = -1;
2831
+ }
2832
+ if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
2833
+ g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
2448
2834
  return pStatus;
2835
+ }
2449
2836
  ++pStatus;
2450
2837
  }
2451
2838
  return NULL;
2452
2839
  }
2453
2840
 
2454
2841
 
2842
+ void LSAPI_reset_server_state( void )
2843
+ {
2844
+ /*
2845
+ Reset child status
2846
+ */
2847
+ g_prefork_server->m_iCurChildren = 0;
2848
+ lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2849
+ lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2850
+ while( pStatus < pEnd )
2851
+ {
2852
+ pStatus->m_pid = 0;
2853
+ ++pStatus;
2854
+ }
2855
+ if (s_busy_workers)
2856
+ __sync_lock_release(s_busy_workers);
2857
+ if (s_accepting_workers)
2858
+ __sync_lock_release(s_accepting_workers);
2859
+
2860
+ }
2861
+
2455
2862
 
2456
2863
  static void lsapi_sigchild( int signal )
2457
2864
  {
2458
2865
  int status, pid;
2459
2866
  lsapi_child_status * child_status;
2867
+ if (g_prefork_server == NULL)
2868
+ return;
2460
2869
  while( 1 )
2461
2870
  {
2462
2871
  pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
@@ -2468,25 +2877,60 @@ static void lsapi_sigchild( int signal )
2468
2877
  {
2469
2878
  int sig_num = WTERMSIG( status );
2470
2879
  int dump = WCOREDUMP( status );
2471
- fprintf( stderr, "Child process with pid: %d was killed by signal: %d, core dump: %d\n", pid, sig_num, dump );
2880
+ lsapi_log("Child process with pid: %d was killed by signal: "
2881
+ "%d, core dump: %d\n", pid, sig_num, dump );
2882
+ }
2883
+ if ( pid == s_pid_dump_debug_info )
2884
+ {
2885
+ pid = 0;
2886
+ continue;
2887
+ }
2888
+ if ( pid == s_ignore_pid )
2889
+ {
2890
+ pid = 0;
2891
+ s_ignore_pid = -1;
2892
+ continue;
2472
2893
  }
2473
2894
  child_status = find_child_status( pid );
2474
2895
  if ( child_status )
2475
2896
  {
2897
+ if (__sync_bool_compare_and_swap(&child_status->m_state,
2898
+ LSAPI_STATE_CONNECTED,
2899
+ LSAPI_STATE_IDLE))
2900
+ {
2901
+ if (s_busy_workers)
2902
+ __sync_fetch_and_sub(s_busy_workers, 1);
2903
+ }
2904
+ else if (__sync_bool_compare_and_swap(&child_status->m_state,
2905
+ LSAPI_STATE_ACCEPTING,
2906
+ LSAPI_STATE_IDLE))
2907
+ {
2908
+ if (s_accepting_workers)
2909
+ __sync_fetch_and_sub(s_accepting_workers, 1);
2910
+ }
2476
2911
  child_status->m_pid = 0;
2477
2912
  --g_prefork_server->m_iCurChildren;
2478
2913
  }
2479
2914
  }
2915
+ while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus )
2916
+ &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 ))
2917
+ --g_prefork_server->m_pChildrenStatusCur;
2480
2918
 
2481
2919
  }
2482
2920
 
2483
- static int lsapi_init_children_status()
2921
+
2922
+ static int lsapi_init_children_status(void)
2484
2923
  {
2924
+ char * pBuf;
2485
2925
  int size = 4096;
2926
+ int max_children;
2927
+ if (g_prefork_server->m_pChildrenStatus)
2928
+ return 0;
2929
+ max_children = g_prefork_server->m_iMaxChildren
2930
+ + g_prefork_server->m_iExtraChildren;
2486
2931
 
2487
- char * pBuf;
2488
- size = g_prefork_server->m_iMaxChildren * sizeof( lsapi_child_status ) * 2;
2489
- size = (size + 4095 ) / 4096 * 4096;
2932
+ size = max_children * sizeof( lsapi_child_status ) * 2 + 3 * sizeof(int);
2933
+ size = (size + 4095) / 4096 * 4096;
2490
2934
  pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
2491
2935
  MAP_ANON | MAP_SHARED, -1, 0 );
2492
2936
  if ( pBuf == MAP_FAILED )
@@ -2495,25 +2939,47 @@ static int lsapi_init_children_status()
2495
2939
  return -1;
2496
2940
  }
2497
2941
  memset( pBuf, 0, size );
2498
- g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
2942
+ g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
2943
+ g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf;
2944
+ g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + max_children;
2945
+ s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd;
2946
+ s_accepting_workers = s_busy_workers + 1;
2947
+ s_global_counter = s_accepting_workers + 1;
2948
+ s_avail_pages = (size_t *)(s_global_counter + 1);
2949
+
2950
+ setsid();
2499
2951
  return 0;
2500
2952
  }
2501
2953
 
2954
+
2502
2955
  static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
2503
2956
  {
2504
2957
  char achCmd[1024];
2505
- int pid = fork();
2506
- if ( pid != 0 )
2507
- return;
2508
- fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n",
2509
- ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter,
2510
- tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
2511
- snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" -ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", pStatus->m_pid, pStatus->m_pid );
2512
- if ( system( achCmd ) == -1 )
2513
- perror( "system()" );
2514
- exit( 0 );
2958
+ if ( s_pid_dump_debug_info )
2959
+ {
2960
+ if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
2961
+ return;
2962
+ }
2963
+
2964
+ lsapi_log("Possible runaway process, UID: %d, PPID: %d, PID: %d, "
2965
+ "reqCount: %d, process time: %ld, checkpoint time: %ld, start "
2966
+ "time: %ld\n", getuid(), getppid(), pStatus->m_pid,
2967
+ pStatus->m_iReqCounter, tmCur - pStatus->m_tmReqBegin,
2968
+ tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
2969
+
2970
+ s_pid_dump_debug_info = fork();
2971
+ if (s_pid_dump_debug_info == 0)
2972
+ {
2973
+ snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" "
2974
+ "-ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2",
2975
+ pStatus->m_pid, pStatus->m_pid );
2976
+ if ( system( achCmd ) == -1 )
2977
+ perror( "system()" );
2978
+ exit( 0 );
2979
+ }
2515
2980
  }
2516
2981
 
2982
+
2517
2983
  static void lsapi_check_child_status( long tmCur )
2518
2984
  {
2519
2985
  int idle = 0;
@@ -2521,26 +2987,30 @@ static void lsapi_check_child_status( long tmCur )
2521
2987
  int dying = 0;
2522
2988
  int count = 0;
2523
2989
  lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2524
- lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
2990
+ lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur;
2525
2991
  while( pStatus < pEnd )
2526
2992
  {
2527
2993
  tobekilled = 0;
2528
- if ( pStatus->m_pid != 0 )
2994
+ if ( pStatus->m_pid != 0 && pStatus->m_pid != -1)
2529
2995
  {
2530
2996
  ++count;
2531
2997
  if ( !pStatus->m_inProcess )
2532
2998
  {
2533
-
2534
- if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
2535
- ( idle > g_prefork_server->m_iMaxIdleChildren ))
2999
+
3000
+ if (g_prefork_server->m_iCurChildren - dying
3001
+ > g_prefork_server->m_iMaxChildren
3002
+ || idle > g_prefork_server->m_iMaxIdleChildren)
2536
3003
  {
2537
- tobekilled = SIGUSR1;
3004
+ ++pStatus->m_iKillSent;
3005
+ //tobekilled = SIGUSR1;
2538
3006
  }
2539
3007
  else
2540
3008
  {
2541
- if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 ))
3009
+ if (s_max_idle_secs> 0
3010
+ && tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5)
2542
3011
  {
2543
- tobekilled = SIGUSR1;
3012
+ ++pStatus->m_iKillSent;
3013
+ //tobekilled = SIGUSR1;
2544
3014
  }
2545
3015
  }
2546
3016
  if ( !tobekilled )
@@ -2548,62 +3018,88 @@ static void lsapi_check_child_status( long tmCur )
2548
3018
  }
2549
3019
  else
2550
3020
  {
2551
- if ( tmCur - pStatus->m_tmReqBegin >
2552
- g_prefork_server->m_iMaxReqProcessTime )
3021
+ if (tmCur - pStatus->m_tmReqBegin >
3022
+ g_prefork_server->m_iMaxReqProcessTime)
2553
3023
  {
2554
- if (( ( pStatus->m_iKillSent % 5 ) == 0 )&&( s_dump_debug_info ))
3024
+ if ((pStatus->m_iKillSent % 5) == 0 && s_dump_debug_info)
2555
3025
  dump_debug_info( pStatus, tmCur );
2556
3026
  if ( pStatus->m_iKillSent > 5 )
2557
3027
  {
2558
3028
  tobekilled = SIGKILL;
2559
- fprintf( stderr, "Force killing runaway process PID: %d with SIGKILL\n", pStatus->m_pid );
3029
+ lsapi_log("Force killing runaway process PID: %d"
3030
+ " with SIGKILL\n", pStatus->m_pid );
2560
3031
  }
2561
3032
  else
2562
3033
  {
2563
3034
  tobekilled = SIGTERM;
2564
- fprintf( stderr, "Killing runaway process PID: %d with SIGTERM\n", pStatus->m_pid );
3035
+ lsapi_log("Killing runaway process PID: %d with "
3036
+ "SIGTERM\n", pStatus->m_pid );
2565
3037
  }
2566
3038
  }
2567
3039
  }
2568
3040
  if ( tobekilled )
2569
3041
  {
2570
- kill( pStatus->m_pid, tobekilled );
2571
- ++pStatus->m_iKillSent;
2572
- ++dying;
3042
+ if (( kill( pStatus->m_pid, tobekilled ) == -1 ) &&
3043
+ ( errno == ESRCH ))
3044
+ {
3045
+ pStatus->m_pid = 0;
3046
+ --count;
3047
+ }
3048
+ else
3049
+ {
3050
+ ++pStatus->m_iKillSent;
3051
+ ++dying;
3052
+ }
2573
3053
  }
2574
3054
  }
2575
3055
  ++pStatus;
2576
3056
  }
2577
- if ( g_prefork_server->m_iCurChildren != count )
3057
+ if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
2578
3058
  {
2579
- fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Childen: %d, count: %d, idle: %d, dying: %d\n", getpid(),
2580
- g_prefork_server->m_iCurChildren, count, idle, dying );
2581
-
3059
+ lsapi_log("Children tracking is wrong: Cur Children: %d,"
3060
+ " count: %d, idle: %d, dying: %d\n",
3061
+ g_prefork_server->m_iCurChildren, count, idle, dying );
2582
3062
  }
2583
3063
  }
2584
3064
 
2585
- static int lsapi_all_children_must_die()
2586
- {
2587
- int maxWait;
2588
- int sec =0;
2589
- g_prefork_server->m_iMaxReqProcessTime = 10;
2590
- g_prefork_server->m_iMaxIdleChildren = -1;
2591
- maxWait = 15;
2592
3065
 
2593
- while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
2594
- {
2595
- lsapi_check_child_status(time(NULL));
2596
- sleep( 1 );
2597
- sec++;
2598
- }
2599
- if ( g_prefork_server->m_iCurChildren != 0 )
2600
- kill( -getpgrp(), SIGKILL );
2601
- return 0;
2602
- }
3066
+ //static int lsapi_all_children_must_die(void)
3067
+ //{
3068
+ // int maxWait;
3069
+ // int sec =0;
3070
+ // g_prefork_server->m_iMaxReqProcessTime = 10;
3071
+ // g_prefork_server->m_iMaxIdleChildren = -1;
3072
+ // maxWait = 15;
3073
+ //
3074
+ // while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
3075
+ // {
3076
+ // lsapi_check_child_status(time(NULL));
3077
+ // sleep( 1 );
3078
+ // sec++;
3079
+ // }
3080
+ // if ( g_prefork_server->m_iCurChildren != 0 )
3081
+ // kill( -getpgrp(), SIGKILL );
3082
+ // return 0;
3083
+ //}
3084
+
2603
3085
 
3086
+ void set_skip_write()
3087
+ { s_skip_write = 1; }
2604
3088
 
2605
3089
 
2606
- static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq )
3090
+ int is_enough_free_mem()
3091
+ {
3092
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3093
+ //minimum 1GB or 10% available free memory
3094
+ return (*s_avail_pages > s_min_avail_pages
3095
+ || (*s_avail_pages * 10) / s_total_pages > 0);
3096
+ #endif
3097
+ return 1;
3098
+ }
3099
+
3100
+
3101
+ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
3102
+ LSAPI_Request * pReq )
2607
3103
  {
2608
3104
  struct sigaction act, old_term, old_quit, old_int,
2609
3105
  old_usr1, old_child;
@@ -2616,12 +3112,14 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
2616
3112
  fd_set readfds;
2617
3113
  struct timeval timeout;
2618
3114
 
3115
+ sigset_t mask;
3116
+ sigset_t orig_mask;
3117
+
2619
3118
  lsapi_init_children_status();
2620
-
2621
- setsid();
2622
3119
 
2623
3120
  act.sa_flags = 0;
2624
3121
  act.sa_handler = lsapi_sigchild;
3122
+ sigemptyset(&(act.sa_mask));
2625
3123
  if( sigaction( SIGCHLD, &act, &old_child ) )
2626
3124
  {
2627
3125
  perror( "Can't set signal handler for SIGCHILD" );
@@ -2631,6 +3129,7 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
2631
3129
  /* Set up handler to kill children upon exit */
2632
3130
  act.sa_flags = 0;
2633
3131
  act.sa_handler = lsapi_cleanup;
3132
+ sigemptyset(&(act.sa_mask));
2634
3133
  if( sigaction( SIGTERM, &act, &old_term ) ||
2635
3134
  sigaction( SIGINT, &act, &old_int ) ||
2636
3135
  sigaction( SIGUSR1, &act, &old_usr1 ) ||
@@ -2639,14 +3138,18 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
2639
3138
  perror( "Can't set signals" );
2640
3139
  return -1;
2641
3140
  }
2642
- s_stop = 0;
3141
+
2643
3142
  while( !s_stop )
2644
3143
  {
3144
+ if (s_proc_group_timer_cb != NULL) {
3145
+ s_proc_group_timer_cb(&s_ignore_pid);
3146
+ }
3147
+
2645
3148
  curTime = time( NULL );
2646
3149
  if (curTime != lastTime )
2647
3150
  {
2648
3151
  lastTime = curTime;
2649
- if (s_ppid && (getppid() != s_ppid ))
3152
+ if (lsapi_parent_dead())
2650
3153
  break;
2651
3154
  lsapi_check_child_status(curTime );
2652
3155
  if (pServer->m_iServerMaxIdle)
@@ -2662,27 +3165,31 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
2662
3165
  }
2663
3166
  }
2664
3167
 
2665
- if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) )
2666
- {
2667
- usleep( 100000 );
2668
- continue;
2669
- }
3168
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3169
+ *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
3170
+ // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
3171
+ // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
2670
3172
 
3173
+ #endif
2671
3174
  FD_ZERO( &readfds );
2672
3175
  FD_SET( pServer->m_fd, &readfds );
2673
- timeout.tv_sec = 1; timeout.tv_usec = 0;
2674
- if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 )
3176
+ timeout.tv_sec = 1;
3177
+ timeout.tv_usec = 0;
3178
+ ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
3179
+ if (ret == 1 )
2675
3180
  {
2676
- /*
2677
- if ( pServer->m_iCurChildren >= 0 )
3181
+ int accepting = 0;
3182
+ if (s_accepting_workers)
3183
+ accepting = __sync_add_and_fetch(s_accepting_workers, 0);
3184
+
3185
+ if (pServer->m_iCurChildren > 0
3186
+ && accepting > 0)
2678
3187
  {
2679
- usleep( 10 );
2680
- FD_ZERO( &readfds );
2681
- FD_SET( pServer->m_fd, &readfds );
2682
- timeout.tv_sec = 0; timeout.tv_usec = 0;
2683
- if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 )
2684
- continue;
2685
- }*/
3188
+ usleep( 400);
3189
+ while(accepting-- > 0)
3190
+ sched_yield();
3191
+ continue;
3192
+ }
2686
3193
  }
2687
3194
  else if ( ret == -1 )
2688
3195
  {
@@ -2696,21 +3203,60 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
2696
3203
  continue;
2697
3204
  }
2698
3205
 
3206
+ if (pServer->m_iCurChildren >=
3207
+ pServer->m_iMaxChildren + pServer->m_iExtraChildren)
3208
+ {
3209
+ lsapi_log("Reached max children process limit: %d, extra: %d,"
3210
+ " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
3211
+ pServer->m_iMaxChildren, pServer->m_iExtraChildren,
3212
+ pServer->m_iCurChildren,
3213
+ s_busy_workers ? *s_busy_workers : -1 );
3214
+ usleep( 100000 );
3215
+ continue;
3216
+ }
3217
+
2699
3218
  pReq->m_fd = lsapi_accept( pServer->m_fd );
2700
3219
  if ( pReq->m_fd != -1 )
2701
3220
  {
3221
+ wait_secs = 0;
2702
3222
  child_status = find_child_status( 0 );
2703
- if ( child_status )
2704
- memset( child_status, 0, sizeof( *child_status ) );
3223
+
3224
+ sigemptyset( &mask );
3225
+ sigaddset( &mask, SIGCHLD );
3226
+
3227
+ if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 )
3228
+ {
3229
+ perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
3230
+ }
3231
+
2705
3232
  pid = fork();
3233
+
2706
3234
  if ( !pid )
2707
3235
  {
3236
+ setsid();
3237
+ if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
3238
+ perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
2708
3239
  g_prefork_server = NULL;
2709
3240
  s_ppid = getppid();
3241
+ s_pid = getpid();
2710
3242
  s_req_processed = 0;
2711
- s_pChildStatus = child_status;
3243
+ s_proc_group_timer_cb = NULL;
3244
+ s_worker_status = child_status;
3245
+
3246
+ if (pthread_atfork_func)
3247
+ (*pthread_atfork_func)(NULL, NULL, set_skip_write);
3248
+
3249
+ __sync_lock_test_and_set(&s_worker_status->m_state,
3250
+ LSAPI_STATE_CONNECTED);
3251
+ if (s_busy_workers)
3252
+ __sync_add_and_fetch(s_busy_workers, 1);
2712
3253
  lsapi_set_nblock( pReq->m_fd, 0 );
2713
- if ( pReq->m_fdListen != -1 )
3254
+ //keep it open if busy_count is used.
3255
+ if (s_busy_workers
3256
+ && *s_busy_workers > (pServer->m_iMaxChildren >> 1))
3257
+ s_keepListener = 1;
3258
+ if ((s_uid == 0 || !s_keepListener || !is_enough_free_mem())
3259
+ && pReq->m_fdListen != -1 )
2714
3260
  {
2715
3261
  close( pReq->m_fdListen );
2716
3262
  pReq->m_fdListen = -1;
@@ -2723,13 +3269,16 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
2723
3269
  sigaction( SIGUSR1, &old_usr1, 0 );
2724
3270
  //init_conn_key( pReq->m_fd );
2725
3271
  lsapi_notify_pid( pReq->m_fd );
2726
- if ( s_accept_notify )
2727
- return notify_req_received( pReq->m_fd );
3272
+ s_notified_pid = 1;
3273
+ //if ( s_accept_notify )
3274
+ // return notify_req_received( pReq->m_fd );
2728
3275
  return 0;
2729
3276
  }
2730
3277
  else if ( pid == -1 )
2731
3278
  {
2732
- perror( "fork() failed, please increase process limit" );
3279
+ lsapi_perror("fork() failed, please increase process limit", errno);
3280
+ if (child_status)
3281
+ child_status->m_pid = 0;
2733
3282
  }
2734
3283
  else
2735
3284
  {
@@ -2744,27 +3293,230 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
2744
3293
  close( pReq->m_fd );
2745
3294
  pReq->m_fd = -1;
2746
3295
 
3296
+ if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
3297
+ perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" );
3298
+
2747
3299
  }
2748
3300
  else
2749
3301
  {
2750
3302
  if (( errno == EINTR )||( errno == EAGAIN))
2751
3303
  continue;
2752
- perror( "accept() failed" );
3304
+ lsapi_perror("accept() failed", errno);
2753
3305
  return -1;
2754
3306
  }
2755
3307
  }
2756
3308
  sigaction( SIGUSR1, &old_usr1, 0 );
2757
- kill( -getpgrp(), SIGUSR1 );
2758
- lsapi_all_children_must_die(); /* Sorry, children ;-) */
3309
+ //kill( -getpgrp(), SIGUSR1 );
3310
+ //lsapi_all_children_must_die(); /* Sorry, children ;-) */
2759
3311
  return -1;
2760
3312
 
2761
3313
  }
2762
3314
 
2763
- void lsapi_error( const char * pMessage, int err_no )
3315
+
3316
+ static struct sigaction old_term, old_quit, old_int,
3317
+ old_usr1, old_child;
3318
+
3319
+
3320
+ int LSAPI_Postfork_Child(LSAPI_Request * pReq)
3321
+ {
3322
+ int max_children = g_prefork_server->m_iMaxChildren;
3323
+ s_pid = getpid();
3324
+ __sync_lock_test_and_set(&pReq->child_status->m_pid, s_pid);
3325
+ s_worker_status = pReq->child_status;
3326
+
3327
+ setsid();
3328
+ g_prefork_server = NULL;
3329
+ s_ppid = getppid();
3330
+ s_req_processed = 0;
3331
+ s_proc_group_timer_cb = NULL;
3332
+
3333
+ if (pthread_atfork_func)
3334
+ (*pthread_atfork_func)(NULL, NULL, set_skip_write);
3335
+
3336
+ __sync_lock_test_and_set(&s_worker_status->m_state,
3337
+ LSAPI_STATE_CONNECTED);
3338
+ if (s_busy_workers)
3339
+ __sync_add_and_fetch(s_busy_workers, 1);
3340
+ lsapi_set_nblock( pReq->m_fd, 0 );
3341
+ //keep it open if busy_count is used.
3342
+ if (s_busy_workers
3343
+ && *s_busy_workers > (max_children >> 1))
3344
+ s_keepListener = 1;
3345
+ if ((s_uid == 0 || !s_keepListener || !is_enough_free_mem())
3346
+ && pReq->m_fdListen != -1 )
3347
+ {
3348
+ close(pReq->m_fdListen);
3349
+ pReq->m_fdListen = -1;
3350
+ }
3351
+
3352
+ //init_conn_key( pReq->m_fd );
3353
+ lsapi_notify_pid(pReq->m_fd);
3354
+ s_notified_pid = 1;
3355
+ //if ( s_accept_notify )
3356
+ // return notify_req_received( pReq->m_fd );
3357
+ return 0;
3358
+ }
3359
+
3360
+
3361
+ int LSAPI_Postfork_Parent(LSAPI_Request * pReq)
3362
+ {
3363
+ ++g_prefork_server->m_iCurChildren;
3364
+ if (pReq->child_status)
3365
+ {
3366
+ time_t curTime = time( NULL );
3367
+ pReq->child_status->m_tmWaitBegin = curTime;
3368
+ pReq->child_status->m_tmStart = curTime;
3369
+ }
3370
+ close(pReq->m_fd);
3371
+ pReq->m_fd = -1;
3372
+ return 0;
3373
+ }
3374
+
3375
+
3376
+ int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
2764
3377
  {
2765
- fprintf( stderr, "%d: %s, errno: %d (%s)\n", getpid(), pMessage, err_no, strerror( err_no ) );
3378
+ time_t lastTime = 0;
3379
+ time_t curTime = 0;
3380
+ fd_set readfds;
3381
+ struct timeval timeout;
3382
+ int wait_secs = 0;
3383
+ int ret = 0;
3384
+
3385
+ lsapi_prefork_server * pServer = g_prefork_server;
3386
+
3387
+ struct sigaction act;
3388
+
3389
+ lsapi_init_children_status();
3390
+
3391
+ act.sa_flags = 0;
3392
+ act.sa_handler = lsapi_sigchild;
3393
+ sigemptyset(&(act.sa_mask));
3394
+ if (sigaction(SIGCHLD, &act, &old_child))
3395
+ {
3396
+ perror( "Can't set signal handler for SIGCHILD" );
3397
+ return -1;
3398
+ }
3399
+
3400
+ /* Set up handler to kill children upon exit */
3401
+ act.sa_flags = 0;
3402
+ act.sa_handler = lsapi_cleanup;
3403
+ sigemptyset(&(act.sa_mask));
3404
+ if (sigaction(SIGTERM, &act, &old_term) ||
3405
+ sigaction(SIGINT, &act, &old_int ) ||
3406
+ sigaction(SIGUSR1, &act, &old_usr1) ||
3407
+ sigaction(SIGQUIT, &act, &old_quit))
3408
+ {
3409
+ perror( "Can't set signals" );
3410
+ return -1;
3411
+ }
3412
+ s_stop = 0;
3413
+ pReq->m_reqState = 0;
3414
+
3415
+ while(!s_stop)
3416
+ {
3417
+ if (s_proc_group_timer_cb != NULL) {
3418
+ s_proc_group_timer_cb(&s_ignore_pid);
3419
+ }
3420
+
3421
+ curTime = time(NULL);
3422
+ if (curTime != lastTime)
3423
+ {
3424
+ lastTime = curTime;
3425
+ if (lsapi_parent_dead())
3426
+ break;
3427
+ lsapi_check_child_status(curTime);
3428
+ if (pServer->m_iServerMaxIdle)
3429
+ {
3430
+ if (pServer->m_iCurChildren <= 0)
3431
+ {
3432
+ ++wait_secs;
3433
+ if ( wait_secs > pServer->m_iServerMaxIdle )
3434
+ return -1;
3435
+ }
3436
+ else
3437
+ wait_secs = 0;
3438
+ }
3439
+ }
3440
+
3441
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3442
+ *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
3443
+ // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
3444
+ // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
3445
+
3446
+ #endif
3447
+ FD_ZERO(&readfds);
3448
+ FD_SET(pServer->m_fd, &readfds);
3449
+ timeout.tv_sec = 1;
3450
+ timeout.tv_usec = 0;
3451
+ ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
3452
+ if (ret == 1 )
3453
+ {
3454
+ int accepting = 0;
3455
+ if (s_accepting_workers)
3456
+ accepting = __sync_add_and_fetch(s_accepting_workers, 0);
3457
+
3458
+ if (pServer->m_iCurChildren > 0
3459
+ && accepting > 0)
3460
+ {
3461
+ usleep( 400);
3462
+ while(accepting-- > 0)
3463
+ sched_yield();
3464
+ continue;
3465
+ }
3466
+ }
3467
+ else if (ret == -1)
3468
+ {
3469
+ if (errno == EINTR)
3470
+ continue;
3471
+ /* perror( "select()" ); */
3472
+ break;
3473
+ }
3474
+ else
3475
+ {
3476
+ continue;
3477
+ }
3478
+
3479
+ if (pServer->m_iCurChildren >=
3480
+ pServer->m_iMaxChildren + pServer->m_iExtraChildren)
3481
+ {
3482
+ lsapi_log("Reached max children process limit: %d, extra: %d,"
3483
+ " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
3484
+ pServer->m_iMaxChildren, pServer->m_iExtraChildren,
3485
+ pServer->m_iCurChildren,
3486
+ s_busy_workers ? *s_busy_workers : -1);
3487
+ usleep(100000);
3488
+ continue;
3489
+ }
3490
+
3491
+ pReq->m_fd = lsapi_accept(pServer->m_fd);
3492
+ if (pReq->m_fd != -1)
3493
+ {
3494
+ wait_secs = 0;
3495
+ pReq->child_status = find_child_status(0);
3496
+
3497
+ ret = 0;
3498
+ break;
3499
+ }
3500
+ else
3501
+ {
3502
+ if ((errno == EINTR) || (errno == EAGAIN))
3503
+ continue;
3504
+ lsapi_perror("accept() failed", errno);
3505
+ ret = -1;
3506
+ break;
3507
+ }
3508
+ }
3509
+
3510
+ sigaction(SIGCHLD, &old_child, 0);
3511
+ sigaction(SIGTERM, &old_term, 0);
3512
+ sigaction(SIGQUIT, &old_quit, 0);
3513
+ sigaction(SIGINT, &old_int, 0);
3514
+ sigaction(SIGUSR1, &old_usr1, 0);
3515
+
3516
+ return ret;
2766
3517
  }
2767
3518
 
3519
+
2768
3520
  int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2769
3521
  {
2770
3522
  int fd;
@@ -2773,8 +3525,10 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2773
3525
  fd_set readfds;
2774
3526
  struct timeval timeout;
2775
3527
 
2776
- LSAPI_Finish_r( pReq );
3528
+ if (s_skip_write)
3529
+ return -1;
2777
3530
 
3531
+ LSAPI_Finish_r( pReq );
2778
3532
 
2779
3533
  if ( g_prefork_server )
2780
3534
  {
@@ -2782,15 +3536,25 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2782
3536
  if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
2783
3537
  return -1;
2784
3538
  }
2785
- if ( s_req_processed >= s_max_reqs )
3539
+ else if (s_req_processed > 0 && s_max_busy_workers > 0 && s_busy_workers)
3540
+ {
3541
+ ret = __sync_fetch_and_add(s_busy_workers, 0);
3542
+ if (ret >= s_max_busy_workers)
3543
+ {
3544
+ send_conn_close_notification(pReq->m_fd);
3545
+ lsapi_close_connection(pReq);
3546
+ }
3547
+ }
3548
+
3549
+ if ( (unsigned int)s_req_processed > s_max_reqs )
2786
3550
  return -1;
2787
3551
 
2788
- if ( s_pChildStatus )
3552
+ if ( s_worker_status )
2789
3553
  {
2790
- s_pChildStatus->m_tmWaitBegin = time( NULL );
3554
+ s_worker_status->m_tmWaitBegin = time( NULL );
2791
3555
  }
2792
3556
 
2793
-
3557
+
2794
3558
  while( g_running )
2795
3559
  {
2796
3560
  if ( pReq->m_fd != -1 )
@@ -2808,23 +3572,44 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2808
3572
  {
2809
3573
  if ( !g_running )
2810
3574
  return -1;
2811
- if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
2812
- return -1;
3575
+ if (s_req_processed && s_worker_status
3576
+ && s_worker_status->m_iKillSent)
3577
+ return -1;
2813
3578
  FD_ZERO( &readfds );
2814
3579
  FD_SET( fd, &readfds );
2815
3580
  timeout.tv_sec = 1;
2816
3581
  timeout.tv_usec = 0;
3582
+ if (fd == pReq->m_fdListen)
3583
+ {
3584
+ if (s_worker_status)
3585
+ __sync_lock_test_and_set(&s_worker_status->m_state,
3586
+ LSAPI_STATE_ACCEPTING);
3587
+ if (s_accepting_workers)
3588
+ __sync_fetch_and_add(s_accepting_workers, 1);
3589
+ }
2817
3590
  ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
3591
+ if (fd == pReq->m_fdListen)
3592
+ {
3593
+ if (s_accepting_workers)
3594
+ __sync_fetch_and_sub(s_accepting_workers, 1);
3595
+ if (s_worker_status)
3596
+ __sync_lock_test_and_set(&s_worker_status->m_state,
3597
+ LSAPI_STATE_IDLE);
3598
+ }
3599
+
2818
3600
  if ( ret == 0 )
2819
3601
  {
2820
- if ( s_pChildStatus )
3602
+ if ( s_worker_status )
2821
3603
  {
2822
- s_pChildStatus->m_inProcess = 0;
3604
+ s_worker_status->m_inProcess = 0;
3605
+ if (fd == pReq->m_fdListen
3606
+ && (s_keepListener != 2 || !is_enough_free_mem()))
3607
+ return -1;
2823
3608
  }
2824
3609
  ++wait_secs;
2825
3610
  if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
2826
3611
  return -1;
2827
- if ( s_ppid &&( getppid() != s_ppid))
3612
+ if ( lsapi_parent_dead() )
2828
3613
  return -1;
2829
3614
  }
2830
3615
  else if ( ret == -1 )
@@ -2836,17 +3621,25 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2836
3621
  }
2837
3622
  else if ( ret >= 1 )
2838
3623
  {
2839
- if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
2840
- return -1;
3624
+ if (s_req_processed && s_worker_status
3625
+ && s_worker_status->m_iKillSent)
3626
+ return -1;
2841
3627
  if ( fd == pReq->m_fdListen )
2842
3628
  {
2843
3629
  pReq->m_fd = lsapi_accept( pReq->m_fdListen );
2844
3630
  if ( pReq->m_fd != -1 )
2845
3631
  {
3632
+ if (s_worker_status)
3633
+ __sync_lock_test_and_set(&s_worker_status->m_state,
3634
+ LSAPI_STATE_CONNECTED);
3635
+ if (s_busy_workers)
3636
+ __sync_fetch_and_add(s_busy_workers, 1);
3637
+
2846
3638
  fd = pReq->m_fd;
3639
+
2847
3640
  lsapi_set_nblock( fd, 0 );
2848
3641
  //init_conn_key( pReq->m_fd );
2849
- if ( !s_keepListener )
3642
+ if (!s_keepListener)
2850
3643
  {
2851
3644
  close( pReq->m_fdListen );
2852
3645
  pReq->m_fdListen = -1;
@@ -2859,7 +3652,7 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2859
3652
  {
2860
3653
  if (( errno == EINTR )||( errno == EAGAIN))
2861
3654
  continue;
2862
- lsapi_error( "lsapi_accept() error", errno );
3655
+ lsapi_perror( "lsapi_accept() error", errno );
2863
3656
  return -1;
2864
3657
  }
2865
3658
  }
@@ -2870,42 +3663,46 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2870
3663
 
2871
3664
  if ( !readReq( pReq ) )
2872
3665
  {
2873
- if ( s_pChildStatus )
3666
+ if ( s_worker_status )
2874
3667
  {
2875
- s_pChildStatus->m_iKillSent = 0;
2876
- s_pChildStatus->m_inProcess = 1;
2877
- ++s_pChildStatus->m_iReqCounter;
2878
- s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL);
3668
+ s_worker_status->m_iKillSent = 0;
3669
+ s_worker_status->m_inProcess = 1;
3670
+ ++s_worker_status->m_iReqCounter;
3671
+ s_worker_status->m_tmReqBegin =
3672
+ s_worker_status->m_tmLastCheckPoint = time(NULL);
2879
3673
  }
2880
3674
  ++s_req_processed;
2881
3675
  return 0;
2882
3676
  }
2883
- lsapi_close( pReq->m_fd );
2884
- pReq->m_fd = -1;
3677
+ lsapi_close_connection(pReq);
2885
3678
  LSAPI_Reset_r( pReq );
2886
3679
  }
2887
3680
  return -1;
2888
-
3681
+
2889
3682
  }
2890
3683
 
3684
+
2891
3685
  void LSAPI_Set_Max_Reqs( int reqs )
2892
- { s_max_reqs = reqs; }
3686
+ { s_max_reqs = reqs - 1; }
2893
3687
 
2894
3688
  void LSAPI_Set_Max_Idle( int secs )
2895
3689
  { s_max_idle_secs = secs; }
2896
3690
 
3691
+
2897
3692
  void LSAPI_Set_Max_Children( int maxChildren )
2898
3693
  {
2899
3694
  if ( g_prefork_server )
2900
3695
  g_prefork_server->m_iMaxChildren = maxChildren;
2901
3696
  }
2902
3697
 
3698
+
2903
3699
  void LSAPI_Set_Extra_Children( int extraChildren )
2904
3700
  {
2905
3701
  if (( g_prefork_server )&&( extraChildren >= 0 ))
2906
3702
  g_prefork_server->m_iExtraChildren = extraChildren;
2907
3703
  }
2908
3704
 
3705
+
2909
3706
  void LSAPI_Set_Max_Process_Time( int secs )
2910
3707
  {
2911
3708
  if (( g_prefork_server )&&( secs > 0 ))
@@ -2919,34 +3716,44 @@ void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
2919
3716
  g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
2920
3717
  }
2921
3718
 
3719
+
2922
3720
  void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
2923
3721
  {
2924
3722
  if ( g_prefork_server )
2925
3723
  g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
2926
3724
  }
2927
3725
 
3726
+
2928
3727
  void LSAPI_Set_Slow_Req_Msecs( int msecs )
2929
3728
  {
2930
3729
  s_slow_req_msecs = msecs;
2931
3730
  }
2932
3731
 
2933
- int LSAPI_Get_Slow_Req_Msecs()
3732
+
3733
+ int LSAPI_Get_Slow_Req_Msecs(void)
2934
3734
  {
2935
3735
  return s_slow_req_msecs;
2936
3736
  }
2937
3737
 
2938
3738
 
2939
- void LSAPI_No_Check_ppid()
3739
+ void LSAPI_No_Check_ppid(void)
2940
3740
  {
2941
3741
  s_ppid = 0;
2942
3742
  }
2943
3743
 
3744
+
3745
+ int LSAPI_Get_ppid()
3746
+ {
3747
+ return(s_ppid);
3748
+ }
3749
+
3750
+
2944
3751
  #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
2945
3752
  #include <crt_externs.h>
2946
3753
  #else
2947
3754
  extern char ** environ;
2948
3755
  #endif
2949
- static void unset_lsapi_envs()
3756
+ static void unset_lsapi_envs(void)
2950
3757
  {
2951
3758
  char **env;
2952
3759
  #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
@@ -2954,26 +3761,162 @@ static void unset_lsapi_envs()
2954
3761
  #else
2955
3762
  env = environ;
2956
3763
  #endif
2957
- while( env != NULL && *env != NULL )
3764
+ while( env != NULL && *env != NULL )
2958
3765
  {
2959
- if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
2960
- || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
2961
- {
3766
+ if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
3767
+ || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
3768
+ {
2962
3769
  char ** del = env;
2963
- do
3770
+ do
2964
3771
  *del = del[1];
2965
3772
  while( *del++ );
2966
3773
  }
2967
3774
  else
2968
3775
  ++env;
2969
- }
3776
+ }
3777
+ }
3778
+
3779
+
3780
+ static int lsapi_initSuEXEC(void)
3781
+ {
3782
+ int i;
3783
+ struct passwd * pw;
3784
+ s_defaultUid = 0;
3785
+ s_defaultGid = 0;
3786
+ if ( s_uid == 0 )
3787
+ {
3788
+ const char * p = getenv( "LSAPI_DEFAULT_UID" );
3789
+ if ( p )
3790
+ {
3791
+ i = atoi( p );
3792
+ if ( i > 0 )
3793
+ s_defaultUid = i;
3794
+ }
3795
+ p = getenv( "LSAPI_DEFAULT_GID" );
3796
+ if ( p )
3797
+ {
3798
+ i = atoi( p );
3799
+ if ( i > 0 )
3800
+ s_defaultGid = i;
3801
+ }
3802
+ p = getenv( "LSAPI_SECRET" );
3803
+ if (( !p )||( readSecret(p) == -1 ))
3804
+ return -1;
3805
+ if ( g_prefork_server )
3806
+ {
3807
+ if ( g_prefork_server->m_iMaxChildren < 100 )
3808
+ g_prefork_server->m_iMaxChildren = 100;
3809
+ if ( g_prefork_server->m_iExtraChildren < 1000 )
3810
+ g_prefork_server->m_iExtraChildren = 1000;
3811
+ }
3812
+ }
3813
+ if ( !s_defaultUid || !s_defaultGid )
3814
+ {
3815
+ pw = getpwnam( "nobody" );
3816
+ if ( pw )
3817
+ {
3818
+ if ( !s_defaultUid )
3819
+ s_defaultUid = pw->pw_uid;
3820
+ if ( !s_defaultGid )
3821
+ s_defaultGid = pw->pw_gid;
3822
+ }
3823
+ else
3824
+ {
3825
+ if ( !s_defaultUid )
3826
+ s_defaultUid = 10000;
3827
+ if ( !s_defaultGid )
3828
+ s_defaultGid = 10000;
3829
+ }
3830
+ }
3831
+ return 0;
3832
+ }
3833
+
3834
+
3835
+ static int lsapi_check_path(const char *p, char *final, int max_len)
3836
+ {
3837
+ char resolved_path[PATH_MAX+1];
3838
+ int len = 0;
3839
+ char *end;
3840
+ if (*p != '/')
3841
+ {
3842
+ if (getcwd(final, max_len) == NULL)
3843
+ return -1;
3844
+ len = strlen(final);
3845
+ *(final + len) = '/';
3846
+ ++len;
3847
+ }
3848
+ end = memccpy(&final[len], p, '\0', PATH_MAX - len);
3849
+ if (!end)
3850
+ {
3851
+ errno = EINVAL;
3852
+ return -1;
3853
+ }
3854
+ p = final;
3855
+ if (realpath(p, resolved_path) == NULL
3856
+ && errno != ENOENT && errno != EACCES)
3857
+ return -1;
3858
+ if (strncmp(resolved_path, "/etc/", 5) == 0)
3859
+ {
3860
+ errno = EPERM;
3861
+ return -1;
3862
+ }
3863
+ return 0;
3864
+ }
3865
+
3866
+
3867
+ static int lsapi_reopen_stderr2(const char *full_path)
3868
+ {
3869
+ int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644);
3870
+ if (newfd == -1)
3871
+ {
3872
+ LSAPI_perror_r(NULL, "Failed to open custom stderr log", full_path);
3873
+ return -1;
3874
+ }
3875
+ if (newfd != 2)
3876
+ {
3877
+ dup2(newfd, 2);
3878
+ close(newfd);
3879
+ dup2(2, 1);
3880
+ }
3881
+ if (s_stderr_log_path && full_path != s_stderr_log_path)
3882
+ {
3883
+ free(s_stderr_log_path);
3884
+ s_stderr_log_path = NULL;
3885
+ }
3886
+ s_stderr_log_path = strdup(full_path);
3887
+ return 0;
3888
+ }
3889
+
3890
+
3891
+ static int lsapi_reopen_stderr(const char *p)
3892
+ {
3893
+ char full_path[PATH_MAX];
3894
+ if (s_uid == 0)
3895
+ return -1;
3896
+ if (lsapi_check_path(p, full_path, PATH_MAX) == -1)
3897
+ {
3898
+ LSAPI_perror_r(NULL, "Invalid custom stderr log path", p);
3899
+ return -1;
3900
+ }
3901
+ return lsapi_reopen_stderr2(full_path);
2970
3902
  }
2971
3903
 
3904
+
2972
3905
  int LSAPI_Init_Env_Parameters( fn_select_t fp )
2973
3906
  {
2974
3907
  const char *p;
3908
+ char ch;
2975
3909
  int n;
2976
3910
  int avoidFork = 0;
3911
+
3912
+ p = getenv("LSAPI_STDERR_LOG");
3913
+ if (p)
3914
+ {
3915
+ lsapi_reopen_stderr(p);
3916
+ }
3917
+ if (!s_stderr_log_path)
3918
+ s_stderr_is_pipe = isPipe(STDERR_FILENO);
3919
+
2977
3920
  p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
2978
3921
  if ( !p )
2979
3922
  p = getenv( "LSAPI_MAX_REQS" );
@@ -2984,11 +3927,29 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
2984
3927
  LSAPI_Set_Max_Reqs( n );
2985
3928
  }
2986
3929
 
3930
+ p = getenv( "LSAPI_KEEP_LISTEN" );
3931
+ if ( p )
3932
+ {
3933
+ n = atoi( p );
3934
+ s_keepListener = n;
3935
+ }
3936
+
2987
3937
  p = getenv( "LSAPI_AVOID_FORK" );
2988
3938
  if ( p )
2989
3939
  {
2990
3940
  avoidFork = atoi( p );
2991
- }
3941
+ if (avoidFork)
3942
+ {
3943
+ s_keepListener = 2;
3944
+ ch = *(p + strlen(p) - 1);
3945
+ if ( ch == 'G' || ch == 'g' )
3946
+ avoidFork *= 1024 * 1024 * 1024;
3947
+ else if ( ch == 'M' || ch == 'm' )
3948
+ avoidFork *= 1024 * 1024;
3949
+ if (avoidFork >= 1024 * 10240)
3950
+ s_min_avail_pages = avoidFork / 4096;
3951
+ }
3952
+ }
2992
3953
 
2993
3954
  p = getenv( "LSAPI_ACCEPT_NOTIFY" );
2994
3955
  if ( p )
@@ -2997,7 +3958,7 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
2997
3958
  }
2998
3959
 
2999
3960
  p = getenv( "LSAPI_SLOW_REQ_MSECS" );
3000
- if ( p )
3961
+ if ( p )
3001
3962
  {
3002
3963
  n = atoi( p );
3003
3964
  LSAPI_Set_Slow_Req_Msecs( n );
@@ -3022,14 +3983,6 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
3022
3983
  LSAPI_Set_Max_Idle( n );
3023
3984
  }
3024
3985
 
3025
- p = getenv( "LSAPI_KEEP_LISTEN" );
3026
- if ( p )
3027
- {
3028
- n = atoi( p );
3029
- s_keepListener = n;
3030
- }
3031
-
3032
-
3033
3986
  if ( LSAPI_Is_Listen() )
3034
3987
  {
3035
3988
  n = 0;
@@ -3040,33 +3993,43 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
3040
3993
  n = atoi( p );
3041
3994
  if ( n > 1 )
3042
3995
  {
3043
- LSAPI_Init_Prefork_Server( n, fp, avoidFork );
3996
+ LSAPI_Init_Prefork_Server( n, fp, avoidFork != 0 );
3044
3997
  LSAPI_Set_Server_fd( g_req.m_fdListen );
3045
3998
  }
3046
3999
 
3047
4000
  p = getenv( "LSAPI_EXTRA_CHILDREN" );
3048
4001
  if ( p )
3049
4002
  LSAPI_Set_Extra_Children( atoi( p ) );
3050
-
4003
+
3051
4004
  p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
3052
4005
  if ( p )
3053
4006
  LSAPI_Set_Max_Idle_Children( atoi( p ) );
3054
-
4007
+
3055
4008
  p = getenv( "LSAPI_PGRP_MAX_IDLE" );
3056
4009
  if ( p )
3057
4010
  {
3058
4011
  LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
3059
4012
  }
3060
-
4013
+
3061
4014
  p = getenv( "LSAPI_MAX_PROCESS_TIME" );
3062
- if ( p )
4015
+ if ( p )
3063
4016
  LSAPI_Set_Max_Process_Time( atoi( p ) );
3064
-
4017
+
3065
4018
  if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
3066
4019
  {
3067
4020
  LSAPI_No_Check_ppid();
3068
4021
  }
3069
4022
 
4023
+ p = getenv("LSAPI_MAX_BUSY_WORKER");
4024
+ if (p)
4025
+ {
4026
+ n = atoi(p);
4027
+ s_max_busy_workers = n;
4028
+ if (n >= 0)
4029
+ LSAPI_No_Check_ppid();
4030
+ }
4031
+
4032
+
3070
4033
  p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
3071
4034
  if ( p )
3072
4035
  s_dump_debug_info = atoi( p );
@@ -3082,7 +4045,25 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
3082
4045
  }
3083
4046
 
3084
4047
 
3085
-
4048
+ int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders,
4049
+ const char * pBody, int bodyLen )
4050
+ {
4051
+ LSAPI_SetRespStatus_r( pReq, code );
4052
+ if ( pRespHeaders )
4053
+ {
4054
+ while( *pRespHeaders )
4055
+ {
4056
+ LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) );
4057
+ ++pRespHeaders;
4058
+ }
4059
+ }
4060
+ if ( pBody &&( bodyLen > 0 ))
4061
+ {
4062
+ LSAPI_Write_r( pReq, pBody, bodyLen );
4063
+ }
4064
+ LSAPI_Finish_r( pReq );
4065
+ return 0;
4066
+ }
3086
4067
 
3087
4068
 
3088
4069
  static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
@@ -3101,6 +4082,7 @@ static void byteReverse(unsigned char *buf, unsigned longs)
3101
4082
  } while (--longs);
3102
4083
  }
3103
4084
 
4085
+
3104
4086
  /*
3105
4087
  * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
3106
4088
  * initialization constants.
@@ -3164,6 +4146,7 @@ void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, uns
3164
4146
  memmove(ctx->in, buf, len);
3165
4147
  }
3166
4148
 
4149
+
3167
4150
  /*
3168
4151
  * Final wrapup - pad to 64-byte boundary with the bit pattern
3169
4152
  * 1 0* (64-bit count of bits processed, MSB-first)
@@ -3206,9 +4189,10 @@ void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
3206
4189
  lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3207
4190
  byteReverse((unsigned char *) ctx->buf, 4);
3208
4191
  memmove(digest, ctx->buf, 16);
3209
- memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
4192
+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
3210
4193
  }
3211
4194
 
4195
+
3212
4196
  /* The four core functions - F1 is optimized somewhat */
3213
4197
 
3214
4198
  /* #define F1(x, y, z) (x & y | ~x & z) */
@@ -3309,3 +4293,18 @@ static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
3309
4293
  buf[3] += d;
3310
4294
  }
3311
4295
 
4296
+
4297
+ int LSAPI_Set_Restored_Parent_Pid(int pid)
4298
+ {
4299
+ int old_ppid = s_ppid;
4300
+ s_restored_ppid = pid;
4301
+ return old_ppid;
4302
+ }
4303
+
4304
+
4305
+ int LSAPI_Inc_Req_Processed(int cnt)
4306
+ {
4307
+ return __sync_add_and_fetch(s_global_counter, cnt);
4308
+ }
4309
+
4310
+