ruby-lsapi 4.3 → 4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/ext/lsapi/lsapilib.c +155 -32
  3. data/lsapi.gemspec +2 -2
  4. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f50f52a087ccb168677d89ab894b8588abec069e
4
- data.tar.gz: 3eebc21ef0cac31cf1f6142a16aab8fe48a1bfd2
3
+ metadata.gz: fb7c17d4bad59b5058a4683b2c07d8abfadc9e36
4
+ data.tar.gz: 0836a55ff1392b8dc1052b2f83732e9b8f992c94
5
5
  SHA512:
6
- metadata.gz: f3143175c96d841ac986629da7208a026df9eda49be225d031fc8fd21f06c18e64ba9a3da53066c427ee4a4d0a54ca86f9b8ec18b4b0b2156c06cb2ca6db4262
7
- data.tar.gz: 7066ddb8f448c3fda956e6b5b29475d15ccaa96e6f8b518359c973f3b66100324d2712ff8af0f89b47b844b9ec94b8382a2ae92f24d61405cbf05ee48057b0b8
6
+ metadata.gz: 417955426a67c9a0a9802a4d18a6ac6d075d8b81a7b01adcf2f4e217b0e15a6b7a0b4cec3bcf40e595e39a89809328840880c860c3907aeab8b08ac83b799436
7
+ data.tar.gz: a0499088de40de67681b2aa0c94ef2fb2248568e7aa9d5c00f668daef3a020e9513c22cf9e2f746ed9eed6d1c2ec1fbb72166930c2b1b0a447fa549753206481
@@ -35,7 +35,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
35
  #include <dlfcn.h>
36
36
  #include <errno.h>
37
37
  #include <fcntl.h>
38
-
38
+ #include <limits.h>
39
39
  #include <sys/stat.h>
40
40
  #include <signal.h>
41
41
  #include <stdlib.h>
@@ -98,7 +98,23 @@ typedef struct lsapi_MD5Context lsapi_MD5_CTX;
98
98
  #define LSAPI_RESP_BUF_SIZE 8192
99
99
  #define LSAPI_INIT_RESP_HEADER_LEN 4096
100
100
 
101
+ typedef struct _lsapi_child_status
102
+ {
103
+ int m_pid;
104
+ long m_tmStart;
101
105
 
106
+ volatile short m_iKillSent;
107
+ volatile char m_inProcess;
108
+ volatile char m_connected;
109
+ volatile int m_iReqCounter;
110
+
111
+ volatile long m_tmWaitBegin;
112
+ volatile long m_tmReqBegin;
113
+ volatile long m_tmLastCheckPoint;
114
+ }
115
+ lsapi_child_status;
116
+
117
+ static lsapi_child_status * s_pChildStatus = NULL;
102
118
 
103
119
  static int g_inited = 0;
104
120
  static int g_running = 1;
@@ -108,12 +124,17 @@ static int s_keepListener = 0;
108
124
  static int s_dump_debug_info = 0;
109
125
  static int s_pid_dump_debug_info = 0;
110
126
 
127
+ static int *s_busy_workers = NULL;
128
+ static int s_max_busy_children = -1;
129
+
111
130
  LSAPI_Request g_req = { -1, -1 };
112
131
 
113
132
  static char s_secret[24];
114
-
133
+ static char *s_pStderrLog = NULL;
115
134
 
116
135
  void Flush_RespBuf_r( LSAPI_Request * pReq );
136
+ static int lsapi_reopen_stderr(const char *p);
137
+
117
138
 
118
139
  static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
119
140
  {
@@ -265,6 +286,20 @@ static int lsapi_close( int fd )
265
286
  }
266
287
  }
267
288
 
289
+
290
+ static void lsapi_close_connection(LSAPI_Request *pReq)
291
+ {
292
+ if (pReq->m_fd == -1)
293
+ return;
294
+ lsapi_close(pReq->m_fd);
295
+ pReq->m_fd = -1;
296
+ if (s_busy_workers)
297
+ __sync_fetch_and_sub(s_busy_workers, 1);
298
+ if (s_pChildStatus)
299
+ s_pChildStatus->m_connected = 0;
300
+ }
301
+
302
+
268
303
  static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
269
304
  {
270
305
  ssize_t ret;
@@ -706,8 +741,11 @@ int LSAPI_is_suEXEC_Daemon(void)
706
741
 
707
742
  static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
708
743
  {
709
- char achError[1024];
710
- int n = snprintf(achError, 1024, "%s:%s: %s\n", pErr1, (pErr2)?pErr2:"", strerror( errno ) );
744
+ char achError[4096];
745
+ int n = snprintf(achError, sizeof(achError), "[%d] %s:%s: %s\n", getpid(),
746
+ pErr1, (pErr2)?pErr2:"", strerror(errno));
747
+ if (n > sizeof(achError))
748
+ n = sizeof(achError);
711
749
  if ( pReq )
712
750
  LSAPI_Write_Stderr_r( pReq, achError, n );
713
751
  else
@@ -908,7 +946,8 @@ static int lsapi_changeUGid( LSAPI_Request * pReq )
908
946
  {
909
947
  int uid = s_defaultUid;
910
948
  int gid = s_defaultGid;
911
- const char * pChroot = NULL;
949
+ const char *pStderrLog;
950
+ const char *pChroot = NULL;
912
951
  struct LSAPI_key_value_pair * pEnv;
913
952
  struct LSAPI_key_value_pair * pAuth;
914
953
  int i;
@@ -973,6 +1012,10 @@ static int lsapi_changeUGid( LSAPI_Request * pReq )
973
1012
  }
974
1013
 
975
1014
  s_uid = uid;
1015
+
1016
+ pStderrLog = LSAPI_GetEnv_r( pReq, "LSAPI_STDERR_LOG");
1017
+ if (pStderrLog)
1018
+ lsapi_reopen_stderr(pStderrLog);
976
1019
 
977
1020
  return 0;
978
1021
 
@@ -1335,6 +1378,10 @@ int LSAPI_Accept_r( LSAPI_Request * pReq )
1335
1378
  }
1336
1379
  else
1337
1380
  {
1381
+ if (s_pChildStatus)
1382
+ s_pChildStatus->m_connected = 1;
1383
+ if (s_busy_workers)
1384
+ __sync_fetch_and_add(s_busy_workers, 1);
1338
1385
  lsapi_set_nblock( pReq->m_fd , 0 );
1339
1386
  if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
1340
1387
  {
@@ -1354,8 +1401,7 @@ int LSAPI_Accept_r( LSAPI_Request * pReq )
1354
1401
  if ( !readReq( pReq ) )
1355
1402
  break;
1356
1403
  //abort();
1357
- lsapi_close( pReq->m_fd );
1358
- pReq->m_fd = -1;
1404
+ lsapi_close_connection(pReq);
1359
1405
  LSAPI_Reset_r( pReq );
1360
1406
  }
1361
1407
  return 0;
@@ -1802,8 +1848,7 @@ int LSAPI_Flush_r( LSAPI_Request * pReq )
1802
1848
  n, pReq->m_totalLen );
1803
1849
  if ( ret < pReq->m_totalLen )
1804
1850
  {
1805
- lsapi_close( pReq->m_fd );
1806
- pReq->m_fd = -1;
1851
+ lsapi_close_connection(pReq);
1807
1852
  ret = -1;
1808
1853
  }
1809
1854
  pReq->m_totalLen = 0;
@@ -1826,7 +1871,7 @@ ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t le
1826
1871
 
1827
1872
  if ( !pReq )
1828
1873
  return -1;
1829
- if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen ))
1874
+ if (s_pStderrLog||( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen ))
1830
1875
  return write( 2, pBuf, len );
1831
1876
  if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1832
1877
  {
@@ -1858,8 +1903,7 @@ ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t le
1858
1903
  2, totalLen );
1859
1904
  if ( ret < totalLen )
1860
1905
  {
1861
- lsapi_close( pReq->m_fd );
1862
- pReq->m_fd = -1;
1906
+ lsapi_close_connection(pReq);
1863
1907
  ret = -1;
1864
1908
  }
1865
1909
  }
@@ -2435,23 +2479,6 @@ int LSAPI_CreateListenSock( const char * pBind, int backlog )
2435
2479
 
2436
2480
  static fn_select_t g_fnSelect = select;
2437
2481
 
2438
- typedef struct _lsapi_child_status
2439
- {
2440
- int m_pid;
2441
- long m_tmStart;
2442
-
2443
- volatile short m_iKillSent;
2444
- volatile short m_inProcess;
2445
- volatile int m_iReqCounter;
2446
-
2447
- volatile long m_tmWaitBegin;
2448
- volatile long m_tmReqBegin;
2449
- volatile long m_tmLastCheckPoint;
2450
- }
2451
- lsapi_child_status;
2452
-
2453
- static lsapi_child_status * s_pChildStatus = NULL;
2454
-
2455
2482
  typedef struct _lsapi_prefork_server
2456
2483
  {
2457
2484
  int m_fd;
@@ -2482,6 +2509,7 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
2482
2509
  if ( max_children >= 10000)
2483
2510
  max_children = 10000;
2484
2511
 
2512
+ s_max_busy_children = max_children / 2 + 1;
2485
2513
 
2486
2514
  g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
2487
2515
  if ( !g_prefork_server )
@@ -2596,9 +2624,14 @@ static void lsapi_sigchild( int signal )
2596
2624
  child_status = find_child_status( pid );
2597
2625
  if ( child_status )
2598
2626
  {
2627
+ if (child_status->m_connected)
2628
+ {
2629
+ if (s_busy_workers)
2630
+ __sync_fetch_and_sub(s_busy_workers, 1);
2631
+ child_status->m_connected = 0;
2632
+ }
2599
2633
  child_status->m_pid = 0;
2600
2634
  --g_prefork_server->m_iCurChildren;
2601
-
2602
2635
  }
2603
2636
  }
2604
2637
  while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus )
@@ -2868,6 +2901,11 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
2868
2901
  s_ppid = getppid();
2869
2902
  s_req_processed = 0;
2870
2903
  s_pChildStatus = child_status;
2904
+
2905
+ s_pChildStatus->m_connected = 1;
2906
+ if (s_busy_workers)
2907
+ __sync_fetch_and_add(s_busy_workers, 1);
2908
+
2871
2909
  lsapi_set_nblock( pReq->m_fd, 0 );
2872
2910
  if ( pReq->m_fdListen != -1 )
2873
2911
  {
@@ -2938,6 +2976,9 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2938
2976
 
2939
2977
  LSAPI_Finish_r( pReq );
2940
2978
 
2979
+ if (s_max_busy_children > 0 && s_busy_workers
2980
+ && *s_busy_workers >= s_max_busy_children)
2981
+ lsapi_close_connection(pReq);
2941
2982
 
2942
2983
  if ( g_prefork_server )
2943
2984
  {
@@ -3006,7 +3047,13 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
3006
3047
  pReq->m_fd = lsapi_accept( pReq->m_fdListen );
3007
3048
  if ( pReq->m_fd != -1 )
3008
3049
  {
3050
+ if (s_pChildStatus)
3051
+ s_pChildStatus->m_connected = 1;
3052
+ if (s_busy_workers)
3053
+ __sync_fetch_and_add(s_busy_workers, 1);
3054
+
3009
3055
  fd = pReq->m_fd;
3056
+
3010
3057
  lsapi_set_nblock( fd, 0 );
3011
3058
  //init_conn_key( pReq->m_fd );
3012
3059
  if ( !s_keepListener )
@@ -3043,8 +3090,7 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
3043
3090
  ++s_req_processed;
3044
3091
  return 0;
3045
3092
  }
3046
- lsapi_close( pReq->m_fd );
3047
- pReq->m_fd = -1;
3093
+ lsapi_close_connection(pReq);
3048
3094
  LSAPI_Reset_r( pReq );
3049
3095
  }
3050
3096
  return -1;
@@ -3187,11 +3233,88 @@ static int lsapi_initSuEXEC(void)
3187
3233
  }
3188
3234
 
3189
3235
 
3236
+ static int lsapi_check_path(const char *p, char *final, int max_len)
3237
+ {
3238
+ char resolved_path[PATH_MAX+1];
3239
+ int len = 0;
3240
+ char *end, *temp;
3241
+ if (*p != '/')
3242
+ {
3243
+ if (getcwd(final, max_len) == NULL)
3244
+ return -1;
3245
+ len = strlen(final);
3246
+ *(final + len) = '/';
3247
+ ++len;
3248
+ }
3249
+ end = memccpy(&final[len], p, '\0', PATH_MAX - len);
3250
+ if (!end)
3251
+ {
3252
+ errno = EINVAL;
3253
+ return -1;
3254
+ }
3255
+ p = final;
3256
+ if (realpath(p, resolved_path) == NULL
3257
+ && errno != ENOENT && errno != EACCES)
3258
+ return -1;
3259
+ if (strncmp(resolved_path, "/etc/", 5) == 0)
3260
+ {
3261
+ errno = EPERM;
3262
+ return -1;
3263
+ }
3264
+ return 0;
3265
+ }
3266
+
3267
+
3268
+ static int lsapi_reopen_stderr2(const char *full_path)
3269
+ {
3270
+ int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644);
3271
+ if (newfd == -1)
3272
+ {
3273
+ LSAPI_perror_r(NULL, "failed to open custom stderr log", full_path);
3274
+ return -1;
3275
+ }
3276
+ if (newfd != 2)
3277
+ {
3278
+ dup2(newfd, 2);
3279
+ close(newfd);
3280
+ dup2(2, 1);
3281
+ }
3282
+ if (s_pStderrLog && full_path != s_pStderrLog)
3283
+ {
3284
+ free(s_pStderrLog);
3285
+ s_pStderrLog = NULL;
3286
+ }
3287
+ s_pStderrLog = strdup(full_path);
3288
+ return 0;
3289
+ }
3290
+
3291
+
3292
+ static int lsapi_reopen_stderr(const char *p)
3293
+ {
3294
+ char full_path[PATH_MAX];
3295
+ if (s_uid == 0)
3296
+ return -1;
3297
+ if (lsapi_check_path(p, full_path, PATH_MAX) == -1)
3298
+ {
3299
+ LSAPI_perror_r(NULL, "invalid custom stderr log path", p);
3300
+ return -1;
3301
+ }
3302
+ return lsapi_reopen_stderr2(full_path);
3303
+ }
3304
+
3305
+
3190
3306
  int LSAPI_Init_Env_Parameters( fn_select_t fp )
3191
3307
  {
3192
3308
  const char *p;
3193
3309
  int n;
3194
3310
  int avoidFork = 0;
3311
+
3312
+ p = getenv("LSAPI_STDERR_LOG");
3313
+ if (p)
3314
+ {
3315
+ lsapi_reopen_stderr(p);
3316
+ }
3317
+
3195
3318
  p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
3196
3319
  if ( !p )
3197
3320
  p = getenv( "LSAPI_MAX_REQS" );
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{ruby-lsapi}
3
- s.version = "4.3"
4
- s.date = %q{2017-03-06}
3
+ s.version = "4.4"
4
+ s.date = %q{2018-01-18}
5
5
  s.description = "This is a ruby extension for fast communication with LiteSpeed Web Server."
6
6
  s.summary = %q{A ruby extension for fast communication with LiteSpeed Web Server.}
7
7
  s.has_rdoc = false
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsapi
3
3
  version: !ruby/object:Gem::Version
4
- version: '4.3'
4
+ version: '4.4'
5
5
  platform: ruby
6
6
  authors:
7
7
  - LiteSpeed Technologies Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-06 00:00:00.000000000 Z
11
+ date: 2018-01-18 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: This is a ruby extension for fast communication with LiteSpeed Web Server.
14
14
  email: info@litespeedtech.com
@@ -49,7 +49,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
49
  version: '0'
50
50
  requirements: []
51
51
  rubyforge_project: ruby-lsapi
52
- rubygems_version: 2.4.5.1
52
+ rubygems_version: 2.2.5
53
53
  signing_key:
54
54
  specification_version: 4
55
55
  summary: A ruby extension for fast communication with LiteSpeed Web Server.