ruby-lsapi 1.13 → 2.0
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.
- 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
|
|