ruby-lsapi 1.13 → 2.0

Sign up to get free protection for your applications and to get access to all the features.
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 int s_children = 0;
47
- static int s_cur_children = 0;
48
- static int s_req_processed = 0;
49
- static int s_max_reqs = 1000000;
50
- static int s_max_idle_secs = 60;
51
- static int s_listenFd = -1;
52
- static int s_ppid = 0;
53
- static int s_max_grp_idle_secs = 0;
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
- LSAPI_Finish_r( &g_req );
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
- while( 1 )
180
+ else
341
181
  {
342
- if ( g_req.m_fd != -1 )
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
- return Qnil;
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
- // lsapi_data *data;
438
- // Data_Get_Struct(self,lsapi_data, data);
439
- if ( LSAPI_Write_r( &g_req, &ch, 1 ) == 1 )
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
- // Data_Get_Struct(self,lsapi_data, data);
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 = LSAPI_Write_r( &g_req, RSTRING(str)->ptr, RSTRING(str)->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
- char * p = getenv( "LSAPI_CHILDREN" );
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
- s_children = atoi( p );
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
- s_max_reqs = n;
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
- s_max_idle_secs = n;
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
- s_max_grp_idle_secs = atoi( p );
540
+ LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
734
541
  ruby_unsetenv( "LSAPI_PGRP_MAX_IDLE" );
735
542
  }
736
543
 
737
- if ( !getenv( "LSAPI_PPID_NO_CHECK" ) )
738
- s_ppid = getppid();
739
- else
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