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/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