ruby-lsapi 1.13 → 2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +71 -35
- data/ext/lsapi/lsapilib.c +729 -4
- data/ext/lsapi/lsapilib.h +31 -1
- data/ext/lsapi/lsruby.c +67 -245
- metadata +4 -3
data/ext/lsapi/lsapilib.h
CHANGED
@@ -49,6 +49,9 @@ extern "C" {
|
|
49
49
|
#include <stddef.h>
|
50
50
|
#include <lsapidef.h>
|
51
51
|
|
52
|
+
#include <sys/time.h>
|
53
|
+
#include <sys/types.h>
|
54
|
+
|
52
55
|
struct LSAPI_key_value_pair
|
53
56
|
{
|
54
57
|
char * pKey;
|
@@ -64,7 +67,10 @@ typedef struct lsapi_request
|
|
64
67
|
{
|
65
68
|
int m_fdListen;
|
66
69
|
int m_fd;
|
67
|
-
|
70
|
+
|
71
|
+
long m_lLastActive;
|
72
|
+
long m_lReqBegin;
|
73
|
+
|
68
74
|
char * m_pReqBuf;
|
69
75
|
int m_reqBufSize;
|
70
76
|
|
@@ -294,6 +300,30 @@ static inline int LSAPI_SetRespStatus( int code )
|
|
294
300
|
|
295
301
|
int LSAPI_IsRunning(void);
|
296
302
|
|
303
|
+
int LSAPI_CreateListenSock( const char * pBind, int backlog );
|
304
|
+
|
305
|
+
typedef int (*fn_select_t)( int, fd_set *, fd_set *, fd_set *, struct timeval * );
|
306
|
+
|
307
|
+
int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp );
|
308
|
+
|
309
|
+
void LSAPI_Set_Server_fd( int fd );
|
310
|
+
|
311
|
+
int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq );
|
312
|
+
|
313
|
+
void LSAPI_Set_Max_Reqs( int reqs );
|
314
|
+
|
315
|
+
void LSAPI_Set_Max_Idle( int secs );
|
316
|
+
|
317
|
+
void LSAPI_Set_Max_Children( int maxChildren );
|
318
|
+
|
319
|
+
void LSAPI_Set_Max_Idle_Children( int maxIdleChld );
|
320
|
+
|
321
|
+
void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle );
|
322
|
+
|
323
|
+
void LSAPI_Set_Max_Process_Time( int secs );
|
324
|
+
|
325
|
+
void LSAPI_Init_Env_Parameters( fn_select_t fp );
|
326
|
+
|
297
327
|
#if defined (c_plusplus) || defined (__cplusplus)
|
298
328
|
}
|
299
329
|
#endif
|
data/ext/lsapi/lsruby.c
CHANGED
@@ -35,6 +35,8 @@ typedef struct lsapi_data
|
|
35
35
|
{
|
36
36
|
LSAPI_Request * req;
|
37
37
|
VALUE env;
|
38
|
+
int (* fn_write)( LSAPI_Request *, const char * , int );
|
39
|
+
|
38
40
|
}lsapi_data;
|
39
41
|
|
40
42
|
|
@@ -43,14 +45,17 @@ static VALUE cLSAPI;
|
|
43
45
|
static VALUE s_req = Qnil;
|
44
46
|
static lsapi_data * s_req_data;
|
45
47
|
|
46
|
-
static
|
47
|
-
static
|
48
|
-
|
49
|
-
static int
|
50
|
-
static int
|
51
|
-
static int
|
52
|
-
static int
|
53
|
-
static int
|
48
|
+
static VALUE s_req_stderr = Qnil;
|
49
|
+
static lsapi_data * s_stderr_data;
|
50
|
+
|
51
|
+
//static int s_children = 0;
|
52
|
+
//static int s_cur_children = 0;
|
53
|
+
//static int s_req_processed = 0;
|
54
|
+
//static int s_max_reqs = 1000000;
|
55
|
+
//static int s_max_idle_secs = 60;
|
56
|
+
//static int s_listenFd = -1;
|
57
|
+
//static int s_ppid = 0;
|
58
|
+
//static int s_max_grp_idle_secs = 0;
|
54
59
|
|
55
60
|
static void lsapi_ruby_setenv(const char *name, const char *value)
|
56
61
|
{
|
@@ -161,164 +166,6 @@ static void setup_cgi_env( lsapi_data * data )
|
|
161
166
|
|
162
167
|
|
163
168
|
|
164
|
-
static int s_stop;
|
165
|
-
void lsapi_cleanup(int signal)
|
166
|
-
{
|
167
|
-
s_stop = signal;
|
168
|
-
}
|
169
|
-
|
170
|
-
void lsapi_sigchild( int signal )
|
171
|
-
{
|
172
|
-
int status, pid;
|
173
|
-
while( 1 )
|
174
|
-
{
|
175
|
-
pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
|
176
|
-
if ( pid <= 0 )
|
177
|
-
{
|
178
|
-
break;
|
179
|
-
}
|
180
|
-
--s_cur_children;
|
181
|
-
}
|
182
|
-
|
183
|
-
}
|
184
|
-
|
185
|
-
static int lsapi_ruby_accept( int fdListen )
|
186
|
-
{
|
187
|
-
int fd;
|
188
|
-
int nodelay = 1;
|
189
|
-
socklen_t len;
|
190
|
-
char achPeer[128];
|
191
|
-
|
192
|
-
len = sizeof( achPeer );
|
193
|
-
fd = accept( s_listenFd, (struct sockaddr *)&achPeer, &len );
|
194
|
-
if ( fd != -1 )
|
195
|
-
{
|
196
|
-
if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
|
197
|
-
{
|
198
|
-
setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
|
199
|
-
(char *)&nodelay, sizeof(nodelay));
|
200
|
-
}
|
201
|
-
}
|
202
|
-
return fd;
|
203
|
-
|
204
|
-
}
|
205
|
-
|
206
|
-
static int lsapi_fork_child()
|
207
|
-
{
|
208
|
-
struct sigaction act, old_term, old_quit, old_int,
|
209
|
-
old_usr1, old_child;
|
210
|
-
|
211
|
-
int wait_secs = 0;
|
212
|
-
int ret;
|
213
|
-
fd_set readfds;
|
214
|
-
struct timeval timeout;
|
215
|
-
|
216
|
-
setsid();
|
217
|
-
|
218
|
-
act.sa_flags = 0;
|
219
|
-
act.sa_handler = lsapi_sigchild;
|
220
|
-
if( sigaction( SIGCHLD, &act, &old_child ) )
|
221
|
-
{
|
222
|
-
perror( "Can't set signal handler for SIGCHILD" );
|
223
|
-
return -1;
|
224
|
-
}
|
225
|
-
|
226
|
-
/* Set up handler to kill children upon exit */
|
227
|
-
act.sa_flags = 0;
|
228
|
-
act.sa_handler = lsapi_cleanup;
|
229
|
-
if( sigaction( SIGTERM, &act, &old_term ) ||
|
230
|
-
sigaction( SIGINT, &act, &old_int ) ||
|
231
|
-
sigaction( SIGUSR1, &act, &old_usr1 ) ||
|
232
|
-
sigaction( SIGQUIT, &act, &old_quit ))
|
233
|
-
{
|
234
|
-
perror( "Can't set signals" );
|
235
|
-
return -1;
|
236
|
-
}
|
237
|
-
s_stop = 0;
|
238
|
-
while( !s_stop )
|
239
|
-
{
|
240
|
-
if ( s_cur_children >= (s_children << 1 ) )
|
241
|
-
{
|
242
|
-
usleep( 10000 );
|
243
|
-
continue;
|
244
|
-
}
|
245
|
-
|
246
|
-
FD_ZERO( &readfds );
|
247
|
-
FD_SET( s_listenFd, &readfds );
|
248
|
-
timeout.tv_sec = 1; timeout.tv_usec = 0;
|
249
|
-
if ((ret = rb_thread_select(s_listenFd+1, &readfds, NULL, NULL, &timeout)) == 1 )
|
250
|
-
{
|
251
|
-
if ( s_cur_children >= 0 )
|
252
|
-
{
|
253
|
-
usleep( 10 );
|
254
|
-
FD_ZERO( &readfds );
|
255
|
-
FD_SET( s_listenFd, &readfds );
|
256
|
-
timeout.tv_sec = 0; timeout.tv_usec = 0;
|
257
|
-
if ( select(s_listenFd+1, &readfds, NULL, NULL, &timeout) == 0 )
|
258
|
-
continue;
|
259
|
-
}
|
260
|
-
}
|
261
|
-
else if ( ret == -1 )
|
262
|
-
break;
|
263
|
-
else
|
264
|
-
{
|
265
|
-
if (s_ppid && (kill(s_ppid, 0) == -1)&&(errno == ESRCH))
|
266
|
-
break;
|
267
|
-
if (s_max_grp_idle_secs)
|
268
|
-
{
|
269
|
-
if ( s_cur_children <= 0 )
|
270
|
-
{
|
271
|
-
++wait_secs;
|
272
|
-
if ( wait_secs > s_max_grp_idle_secs )
|
273
|
-
return -1;
|
274
|
-
}
|
275
|
-
else
|
276
|
-
wait_secs = 0;
|
277
|
-
}
|
278
|
-
continue;
|
279
|
-
}
|
280
|
-
|
281
|
-
g_req.m_fd = lsapi_ruby_accept( s_listenFd );
|
282
|
-
if ( g_req.m_fd != -1 )
|
283
|
-
{
|
284
|
-
int pid = fork();
|
285
|
-
if ( !pid )
|
286
|
-
{
|
287
|
-
s_children = 0;
|
288
|
-
s_ppid = getppid();
|
289
|
-
|
290
|
-
/* don't catch our signals */
|
291
|
-
sigaction( SIGCHLD, &old_child, 0 );
|
292
|
-
sigaction( SIGTERM, &old_term, 0 );
|
293
|
-
sigaction( SIGQUIT, &old_quit, 0 );
|
294
|
-
sigaction( SIGINT, &old_int, 0 );
|
295
|
-
sigaction( SIGUSR1, &old_usr1, 0 );
|
296
|
-
return 0;
|
297
|
-
}
|
298
|
-
else if ( pid == -1 )
|
299
|
-
{
|
300
|
-
perror( "fork() failed, please increase process limit" );
|
301
|
-
}
|
302
|
-
else
|
303
|
-
{
|
304
|
-
++s_cur_children;
|
305
|
-
}
|
306
|
-
close( g_req.m_fd );
|
307
|
-
g_req.m_fd = -1;
|
308
|
-
|
309
|
-
}
|
310
|
-
else
|
311
|
-
{
|
312
|
-
if (( errno == EINTR )||( errno == EAGAIN))
|
313
|
-
continue;
|
314
|
-
perror( "accept() failed" );
|
315
|
-
return -1;
|
316
|
-
}
|
317
|
-
}
|
318
|
-
kill( -getpgrp(), SIGUSR1 );
|
319
|
-
return -1;
|
320
|
-
|
321
|
-
}
|
322
169
|
|
323
170
|
static VALUE lsapi_s_accept( VALUE self )
|
324
171
|
{
|
@@ -328,66 +175,14 @@ static VALUE lsapi_s_accept( VALUE self )
|
|
328
175
|
fd_set readfds;
|
329
176
|
struct timeval timeout;
|
330
177
|
|
331
|
-
|
332
|
-
if ( s_children > 1)
|
333
|
-
{
|
334
|
-
if ( s_listenFd != -1 )
|
335
|
-
if ( lsapi_fork_child() == -1 )
|
336
|
-
return Qnil;
|
337
|
-
}
|
338
|
-
if ( s_req_processed >= s_max_reqs )
|
178
|
+
if ( LSAPI_Prefork_Accept_r( &g_req ) == -1 )
|
339
179
|
return Qnil;
|
340
|
-
|
180
|
+
else
|
341
181
|
{
|
342
|
-
|
343
|
-
|
344
|
-
fd = g_req.m_fd;
|
345
|
-
}
|
346
|
-
else if ( s_listenFd != -1 )
|
347
|
-
fd = s_listenFd;
|
348
|
-
else
|
349
|
-
return Qnil;
|
350
|
-
wait_secs = 0;
|
351
|
-
while( LSAPI_IsRunning() )
|
352
|
-
{
|
353
|
-
FD_ZERO( &readfds );
|
354
|
-
FD_SET( fd, &readfds );
|
355
|
-
timeout.tv_sec = 1;
|
356
|
-
timeout.tv_usec = 0;
|
357
|
-
if (rb_thread_select(fd+1, &readfds, NULL, NULL, &timeout) < 1)
|
358
|
-
{
|
359
|
-
++wait_secs;
|
360
|
-
if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
|
361
|
-
return Qnil;
|
362
|
-
if ( s_ppid &&(kill(s_ppid, 0) == -1)&&(errno == ESRCH))
|
363
|
-
return Qnil;
|
364
|
-
}
|
365
|
-
else if ( fd == s_listenFd )
|
366
|
-
{
|
367
|
-
g_req.m_fd = lsapi_ruby_accept( s_listenFd );
|
368
|
-
if ( g_req.m_fd != -1 )
|
369
|
-
{
|
370
|
-
break;
|
371
|
-
}
|
372
|
-
}
|
373
|
-
else
|
374
|
-
break;
|
375
|
-
}
|
376
|
-
|
377
|
-
ret = LSAPI_Accept_r( &g_req );
|
378
|
-
|
379
|
-
if ( !ret )
|
380
|
-
{
|
381
|
-
++s_req_processed;
|
382
|
-
setup_cgi_env( s_req_data );
|
383
|
-
return s_req;
|
384
|
-
}
|
385
|
-
else if (( g_req.m_fd == -1 )&&( fd != s_listenFd ))
|
386
|
-
continue;
|
387
|
-
else
|
388
|
-
break;
|
182
|
+
setup_cgi_env( s_req_data );
|
183
|
+
return s_req;
|
389
184
|
}
|
390
|
-
|
185
|
+
|
391
186
|
}
|
392
187
|
|
393
188
|
|
@@ -434,9 +229,9 @@ static VALUE lsapi_process( VALUE self )
|
|
434
229
|
static VALUE lsapi_putc(VALUE self, VALUE c)
|
435
230
|
{
|
436
231
|
char ch = NUM2CHR(c);
|
437
|
-
|
438
|
-
|
439
|
-
if (
|
232
|
+
lsapi_data *data;
|
233
|
+
Data_Get_Struct(self,lsapi_data, data);
|
234
|
+
if ( (*data->fn_write)( data->req, &ch, 1 ) == 1 )
|
440
235
|
return c;
|
441
236
|
else
|
442
237
|
return INT2NUM( EOF );
|
@@ -447,11 +242,11 @@ static VALUE lsapi_write( VALUE self, VALUE str )
|
|
447
242
|
{
|
448
243
|
lsapi_data *data;
|
449
244
|
int len;
|
450
|
-
|
245
|
+
Data_Get_Struct(self,lsapi_data, data);
|
451
246
|
// len = LSAPI_Write_r( data->req, RSTRING(str)->ptr, RSTRING(str)->len );
|
452
247
|
if (TYPE(str) != T_STRING)
|
453
248
|
str = rb_obj_as_string(str);
|
454
|
-
len =
|
249
|
+
len = (*data->fn_write)( data->req, RSTRING(str)->ptr, RSTRING(str)->len );
|
455
250
|
return INT2NUM( len );
|
456
251
|
}
|
457
252
|
|
@@ -702,20 +497,32 @@ static VALUE lsapi_setsync(VALUE self,VALUE sync)
|
|
702
497
|
void Init_lsapi()
|
703
498
|
{
|
704
499
|
VALUE remove_env;
|
705
|
-
int n;
|
706
|
-
|
500
|
+
int n = 0;
|
501
|
+
VALUE orig_verbose; // constant silence hack
|
502
|
+
char * p;
|
503
|
+
|
504
|
+
LSAPI_Init();
|
505
|
+
|
506
|
+
LSAPI_Init_Env_Parameters( rb_thread_select );
|
507
|
+
/*
|
508
|
+
p = getenv( "LSAPI_CHILDREN" );
|
707
509
|
if ( p )
|
708
510
|
{
|
709
|
-
|
511
|
+
n = atoi( p );
|
710
512
|
ruby_unsetenv( "LSAPI_CHILDREN" );
|
711
513
|
}
|
514
|
+
if ( n > 1 )
|
515
|
+
{
|
516
|
+
LSAPI_Init_Prefork_Server( n, rb_thread_select );
|
517
|
+
LSAPI_Set_Server_fd( g_req.m_fdListen );
|
518
|
+
}
|
712
519
|
|
713
520
|
p = getenv( "LSAPI_MAX_REQS" );
|
714
521
|
if ( p )
|
715
522
|
{
|
716
523
|
n = atoi( p );
|
717
524
|
if ( n > 0 )
|
718
|
-
|
525
|
+
LSAPI_Set_Max_Req( n );
|
719
526
|
ruby_unsetenv( "LSAPI_MAX_REQS" );
|
720
527
|
}
|
721
528
|
|
@@ -723,21 +530,24 @@ void Init_lsapi()
|
|
723
530
|
if ( p )
|
724
531
|
{
|
725
532
|
n = atoi( p );
|
726
|
-
|
533
|
+
LSAPI_Set_Max_Idle( n );
|
727
534
|
ruby_unsetenv( "LSAPI_MAX_IDLE" );
|
728
535
|
}
|
729
536
|
|
730
537
|
p = getenv( "LSAPI_PGRP_MAX_IDLE" );
|
731
538
|
if ( p )
|
732
539
|
{
|
733
|
-
|
540
|
+
LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
|
734
541
|
ruby_unsetenv( "LSAPI_PGRP_MAX_IDLE" );
|
735
542
|
}
|
736
543
|
|
737
|
-
if (
|
738
|
-
|
739
|
-
|
544
|
+
if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
|
545
|
+
{
|
546
|
+
LSAPI_No_Check_ppid();
|
740
547
|
ruby_unsetenv( "LSAPI_PPID_NO_CHECK" );
|
548
|
+
}
|
549
|
+
*/
|
550
|
+
|
741
551
|
p = getenv( "RAILS_ROOT" );
|
742
552
|
if ( p )
|
743
553
|
{
|
@@ -762,14 +572,6 @@ void Init_lsapi()
|
|
762
572
|
remove_env = rb_str_new( "RAILS_ROOT", 10 );
|
763
573
|
rb_funcall( env_copy, rb_intern( "delete" ), 1, remove_env );
|
764
574
|
|
765
|
-
lsapi_env = rb_hash_new();
|
766
|
-
//redefine ENV using a hash table, should be faster than char **environment
|
767
|
-
rb_define_global_const("ENV", lsapi_env);
|
768
|
-
|
769
|
-
LSAPI_Init();
|
770
|
-
|
771
|
-
s_listenFd = g_req.m_fdListen;
|
772
|
-
g_req.m_fdListen = -1;
|
773
575
|
|
774
576
|
rb_define_global_function("eval_string_wrap", lsapi_eval_string_wrap, 1);
|
775
577
|
|
@@ -801,12 +603,32 @@ void Init_lsapi()
|
|
801
603
|
|
802
604
|
s_req = Data_Make_Struct( cLSAPI, lsapi_data, lsapi_mark, free, s_req_data );
|
803
605
|
s_req_data->req = &g_req;
|
606
|
+
s_req_data->fn_write = LSAPI_Write_r;
|
804
607
|
rb_stdin = rb_stdout = s_req;
|
608
|
+
|
805
609
|
#if RUBY_VERSION_CODE < 180
|
806
610
|
rb_defout = s_req;
|
807
611
|
#endif
|
808
612
|
rb_global_variable(&s_req );
|
809
613
|
|
614
|
+
s_req_stderr = Data_Make_Struct( cLSAPI, lsapi_data, lsapi_mark, free, s_stderr_data );
|
615
|
+
s_stderr_data->req = &g_req;
|
616
|
+
s_stderr_data->fn_write = LSAPI_Write_Stderr_r;
|
617
|
+
rb_stderr = s_req_stderr;
|
618
|
+
rb_global_variable(&s_req_stderr );
|
619
|
+
|
620
|
+
//constant silence hack
|
621
|
+
orig_verbose = (VALUE)ruby_verbose;
|
622
|
+
ruby_verbose = Qnil;
|
623
|
+
|
624
|
+
lsapi_env = rb_hash_new();
|
625
|
+
//redefine ENV using a hash table, should be faster than char **environment
|
626
|
+
rb_define_global_const("ENV", lsapi_env);
|
627
|
+
|
628
|
+
rb_define_global_const("STDERR", rb_stderr);
|
629
|
+
|
630
|
+
ruby_verbose = (VALUE)orig_verbose;
|
631
|
+
|
810
632
|
return;
|
811
633
|
}
|
812
634
|
|