ruby-lsapi 1.3 → 1.4

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -2,7 +2,7 @@
2
2
  lsapi - LSAPI extension for Ruby
3
3
  ================================
4
4
 
5
- Version 0.1.0
5
+ Version 1.4
6
6
 
7
7
  INSTALL
8
8
  -------
@@ -16,8 +16,8 @@ USAGE
16
16
 
17
17
  General CGI scripts
18
18
  ```````````````````
19
- The most efficient way to use LSAPI interface is to modify your CGI script,
20
- you need to add the following to your CGI script
19
+ The most efficient way to use LSAPI interface is to modify your CGI scripts.
20
+ You need to add the following code to your CGI scripts:
21
21
 
22
22
  require 'lsapi'
23
23
 
@@ -28,10 +28,10 @@ you need to add the following to your CGI script
28
28
 
29
29
  end
30
30
 
31
- There is no need to change the way how CGI environment variables being
32
- accessed in your script.
31
+ There is no need to change the way that how CGI environment variables
32
+ are being accessed in your scripts.
33
33
 
34
- There are examples under examples/ folder.
34
+ You can find some examples under examples/ folder.
35
35
 
36
36
 
37
37
  Rails dispatcher
@@ -44,10 +44,10 @@ in public/.htaccess from
44
44
  to
45
45
  RewriteRule ^(.*)$ dispatch.lsapi [QSA,L]
46
46
 
47
- It is very expensive to start a fresh Rails application process, while on
47
+ It is very expensive to start a fresh Rails application process, and on
48
48
  the other hand, server hardware resources can be used more efficiently with
49
- dynamic spawning. In order to solve this conflict, instead of spawning a
50
- fresh Rails process, LSAPI dispatcher can dynamically fork children processes
49
+ dynamic spawning. In order to solve this problem, instead of spawning a
50
+ fresh Rails process, LSAPI dispatcher will dynamically fork children processes
51
51
  off an initialized Rails process.
52
52
 
53
53
  When you configure dispatch.lsapi as a LSAPI application, you should add
@@ -57,12 +57,28 @@ an extra environment variable
57
57
 
58
58
  n should match the "Max Conns" configuration entry of the LSAPI application.
59
59
 
60
+ Two new environment variables has been introduced since Ruby LSAPI 1.4:
61
+
62
+ LSAPI_MAX_REQS=n
63
+
64
+ n is the maximum number of requests that a child process can serve.
65
+ Default value is 1000. Once that number is reached, the child process will
66
+ exit automatically. This will help in case of any memory leaks in Rails.
67
+
68
+ LSAPI_MAX_IDLE=n
69
+
70
+ n is the maximum idle time in seconds that a child process will be waiting
71
+ for a new request. Once it is reached, the child process will quit.
72
+ Default value is 60. When n <= 0, the child process will wait indefinitely.
73
+ This option helps getting rid of idle children processes.
74
+
60
75
 
61
76
  Ruby Script Runner
62
77
  ``````````````````
63
- If you don't want to change your Ruby CGI code, you can use our Ruby script
64
- runner under scripts/ folder. You need to configure lsruby_runner.rb as a
65
- LSAPI application, then add a script handler for "rb" suffix.
78
+ If you don't want to change your existing Ruby CGI code, you can use our
79
+ Ruby script runner under scripts/ folder. You need to configure
80
+ lsruby_runner.rb as a LSAPI application, then add a script handler
81
+ for "rb" suffix.
66
82
 
67
83
 
68
84
  License
@@ -79,6 +95,6 @@ LSAPI ruby extension code is under Ruby license
79
95
  Copyright
80
96
  ---------
81
97
 
82
- Copyright (C) 2006 Lite Speed Technologes Inc.
98
+ Copyright (C) 2006 Lite Speed Technologies Inc.
83
99
 
84
100
 
data/ext/lsapi/lsapilib.c CHANGED
@@ -207,8 +207,18 @@ static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
207
207
  }
208
208
  }
209
209
  }
210
- else if (( ret == -1 )&&( errno != EINTR ))
211
- return ret;
210
+ else if ( ret == -1 )
211
+ {
212
+ if ( errno == EAGAIN )
213
+ {
214
+ if ( totalLen - left > 0 )
215
+ return totalLen - left;
216
+ else
217
+ return -1;
218
+ }
219
+ else if ( errno != EINTR )
220
+ return ret;
221
+ }
212
222
  }
213
223
  return totalLen - left;
214
224
  }
@@ -539,11 +549,16 @@ int LSAPI_Init(void)
539
549
  return 0;
540
550
  }
541
551
 
542
- void LSAPI_stop(void)
552
+ void LSAPI_Stop(void)
543
553
  {
544
554
  g_running = 0;
545
555
  }
546
556
 
557
+ int LSAPI_IsRunning(void)
558
+ {
559
+ return g_running;
560
+ }
561
+
547
562
  int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
548
563
  {
549
564
  if ( !pReq )
@@ -740,7 +755,7 @@ int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int bufLen )
740
755
  bufLen -= len;
741
756
  }
742
757
  else if ( len < 0 )
743
- return -1;
758
+ return (total)?total:-1;
744
759
  }
745
760
  pReq->m_reqBodyRead += total;
746
761
  return total;
data/ext/lsapi/lsapilib.h CHANGED
@@ -121,7 +121,7 @@ typedef int (*LSAPI_CB_EnvHandler )( const char * pKey, int keyLen,
121
121
 
122
122
  int LSAPI_Init(void);
123
123
 
124
- void LSAPI_stop(void);
124
+ void LSAPI_Stop(void);
125
125
 
126
126
  int LSAPI_Is_Listen_r( LSAPI_Request * pReq);
127
127
 
@@ -280,6 +280,7 @@ static inline int LSAPI_AppendRespHeader( char * pBuf, int len )
280
280
  static inline int LSAPI_SetRespStatus( int code )
281
281
  { return LSAPI_SetRespStatus_r( &g_req, code ); }
282
282
 
283
+ int LSAPI_IsRunning(void);
283
284
 
284
285
  #if defined (c_plusplus) || defined (__cplusplus)
285
286
  }
data/ext/lsapi/lsruby.c CHANGED
@@ -42,6 +42,9 @@ static lsapi_data * s_req_data;
42
42
 
43
43
  static int s_children = 0;
44
44
  static int s_cur_children = 0;
45
+ static int s_req_processed = 0;
46
+ static int s_max_reqs = 1000;
47
+ static int s_max_idle_secs = 60;
45
48
 
46
49
  static void lsapi_ruby_setenv(const char *name, const char *value)
47
50
  {
@@ -108,7 +111,7 @@ void lsapi_sigchild( int signal )
108
111
  {
109
112
  break;
110
113
  }
111
-
114
+ --s_cur_children;
112
115
  }
113
116
 
114
117
  }
@@ -120,6 +123,9 @@ static int lsapi_fork_child()
120
123
  char achPeer[128];
121
124
  socklen_t len;
122
125
  int nodelay = 1;
126
+ fd_set readfds;
127
+ struct timeval timeout;
128
+ int ret;
123
129
 
124
130
  setsid();
125
131
 
@@ -145,6 +151,31 @@ static int lsapi_fork_child()
145
151
  s_stop = 0;
146
152
  while( !s_stop )
147
153
  {
154
+ if ( s_cur_children >= (s_children << 1 ) )
155
+ {
156
+ usleep( 10000 );
157
+ continue;
158
+ }
159
+
160
+ FD_ZERO( &readfds );
161
+ FD_SET( g_req.m_fdListen, &readfds );
162
+ timeout.tv_sec = 0; timeout.tv_usec = 100000;
163
+ if ((ret = rb_thread_select(g_req.m_fdListen+1, &readfds, NULL, NULL, &timeout)) == 1 )
164
+ {
165
+ if ( s_cur_children >= s_children )
166
+ {
167
+ usleep( 10 );
168
+ FD_ZERO( &readfds );
169
+ FD_SET( g_req.m_fdListen, &readfds );
170
+ timeout.tv_sec = 0; timeout.tv_usec = 0;
171
+ if ( select(g_req.m_fdListen+1, &readfds, NULL, NULL, &timeout) == 0 )
172
+ continue;
173
+ }
174
+ }
175
+ else if ( ret == -1 )
176
+ break;
177
+ else
178
+ continue;
148
179
  len = sizeof( achPeer );
149
180
  g_req.m_fd = accept( g_req.m_fdListen,
150
181
  (struct sockaddr *)&achPeer, &len );
@@ -158,9 +189,10 @@ static int lsapi_fork_child()
158
189
  int pid = fork();
159
190
  if ( !pid )
160
191
  {
161
- close( g_req.m_fdListen );
162
- g_req.m_fdListen = -1;
163
-
192
+ //close( g_req.m_fdListen );
193
+ //g_req.m_fdListen = -1;
194
+ s_children = 0;
195
+
164
196
  /* don't catch our signals */
165
197
  sigaction( SIGCHLD, &old_child, 0 );
166
198
  sigaction( SIGTERM, &old_term, 0 );
@@ -172,10 +204,11 @@ static int lsapi_fork_child()
172
204
  else if ( pid == -1 )
173
205
  {
174
206
  perror( "fork() failed" );
175
- return -1;
207
+ break;
176
208
  }
177
209
  else
178
210
  {
211
+ ++s_cur_children;
179
212
  close( g_req.m_fd );
180
213
  g_req.m_fd = -1;
181
214
  }
@@ -200,6 +233,8 @@ static VALUE lsapi_s_accept( VALUE self )
200
233
  fd_set readfds;
201
234
  int fd;
202
235
  int ret;
236
+ int wait_secs;
237
+ struct timeval timeout;
203
238
 
204
239
  LSAPI_Finish_r( &g_req );
205
240
  if ( s_children )
@@ -208,36 +243,48 @@ static VALUE lsapi_s_accept( VALUE self )
208
243
  if ( lsapi_fork_child() == -1 )
209
244
  return Qnil;
210
245
  }
211
- if ( g_req.m_fd != -1 )
246
+ if ( s_req_processed < s_max_reqs )
212
247
  {
213
- fd = g_req.m_fd;
214
- }
215
- else if ( g_req.m_fdListen != -1 )
216
- fd = g_req.m_fdListen;
217
- else
218
- return Qnil;
219
-
220
- FD_ZERO( &readfds );
221
- FD_SET( fd, &readfds );
222
-
223
- if (rb_thread_select(fd+1, &readfds, NULL, NULL, NULL) < 1)
224
- {
225
- return Qnil;
226
- }
227
-
228
- ret = LSAPI_Accept_r( &g_req );
229
-
230
- if ( !ret )
231
- {
232
- // req = Data_Make_Struct( self, lsapi_data, lsapi_mark, free, req_data );
233
- // s_req = req;
234
- // req_data->req = &g_req;
235
- // rb_stdin = rb_stdout = req;
236
- //#if RUBY_VERSION_CODE < 180
237
- // rb_defout = req;
238
- //#endif
239
- setup_cgi_env( s_req_data );
240
- return s_req;
248
+ if ( g_req.m_fd != -1 )
249
+ {
250
+ fd = g_req.m_fd;
251
+ }
252
+ else if ( g_req.m_fdListen != -1 )
253
+ fd = g_req.m_fdListen;
254
+ else
255
+ return Qnil;
256
+ wait_secs = 0;
257
+ while( LSAPI_IsRunning() )
258
+ {
259
+ FD_ZERO( &readfds );
260
+ FD_SET( fd, &readfds );
261
+ timeout.tv_sec = 1;
262
+ timeout.tv_usec = 0;
263
+ if (rb_thread_select(fd+1, &readfds, NULL, NULL, &timeout) < 1)
264
+ {
265
+ ++wait_secs;
266
+ if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
267
+ return Qnil;
268
+ }
269
+ else
270
+ break;
271
+ }
272
+
273
+ ret = LSAPI_Accept_r( &g_req );
274
+
275
+ if ( !ret )
276
+ {
277
+ // req = Data_Make_Struct( self, lsapi_data, lsapi_mark, free, req_data );
278
+ // s_req = req;
279
+ // req_data->req = &g_req;
280
+ // rb_stdin = rb_stdout = req;
281
+ //#if RUBY_VERSION_CODE < 180
282
+ // rb_defout = req;
283
+ //#endif
284
+ ++s_req_processed;
285
+ setup_cgi_env( s_req_data );
286
+ return s_req;
287
+ }
241
288
  }
242
289
  return Qnil;
243
290
  }
@@ -435,6 +482,8 @@ static VALUE lsapi_read(int argc, VALUE *argv, VALUE self)
435
482
  lsapi_data *data;
436
483
  int n;
437
484
  int remain;
485
+ fd_set readfds;
486
+ int fd;
438
487
  char buff[8192];
439
488
 
440
489
  if (rb_safe_level() >= 4 && !OBJ_TAINTED(self))
@@ -455,8 +504,16 @@ static VALUE lsapi_read(int argc, VALUE *argv, VALUE self)
455
504
  }
456
505
  str = rb_str_buf_new( remain );
457
506
  OBJ_TAINT(str);
507
+ fd = data->req->m_fd;
458
508
  while( remain > 0 )
459
509
  {
510
+ FD_ZERO( &readfds );
511
+ FD_SET( fd, &readfds );
512
+
513
+ if (rb_thread_select(fd+1, &readfds, NULL, NULL, NULL) < 1)
514
+ {
515
+ return Qnil;
516
+ }
460
517
  n = LSAPI_ReadReqBody_r(data->req, buff,
461
518
  (remain > 8192)?8192:remain );
462
519
  if ( n > 0 )
@@ -519,12 +576,28 @@ static VALUE lsapi_setsync(VALUE self,VALUE sync)
519
576
 
520
577
  void Init_lsapi()
521
578
  {
579
+ int n;
522
580
  char * p = getenv( "LSAPI_CHILDREN" );
523
581
  if ( p )
524
582
  {
525
583
  s_children = atoi( p );
526
584
  }
527
585
 
586
+ p = getenv( "LSAPI_MAX_REQS" );
587
+ if ( p )
588
+ {
589
+ n = atoi( p );
590
+ if ( n > 0 )
591
+ s_max_reqs = n;
592
+ }
593
+
594
+ p = getenv( "LSAPI_MAX_IDLE" );
595
+ if ( p )
596
+ {
597
+ n = atoi( p );
598
+ s_max_idle_secs = n;
599
+ }
600
+
528
601
  orig_stdin = rb_stdin;
529
602
  orig_stdout = rb_stdout;
530
603
  #if RUBY_VERSION_CODE < 180
metadata CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: ruby-lsapi
5
5
  version: !ruby/object:Gem::Version
6
- version: "1.3"
6
+ version: "1.4"
7
7
  date: 2006-07-20 00:00:00 -04:00
8
8
  summary: A ruby extension for fast communication with LiteSpeed Web Server.
9
9
  require_paths: