ruby-lsapi 1.3 → 1.4
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 +29 -13
- data/ext/lsapi/lsapilib.c +19 -4
- data/ext/lsapi/lsapilib.h +2 -1
- data/ext/lsapi/lsruby.c +107 -34
- metadata +1 -1
data/README
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
lsapi - LSAPI extension for Ruby
|
3
3
|
================================
|
4
4
|
|
5
|
-
Version
|
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
|
20
|
-
|
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
|
32
|
-
accessed in your
|
31
|
+
There is no need to change the way that how CGI environment variables
|
32
|
+
are being accessed in your scripts.
|
33
33
|
|
34
|
-
|
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,
|
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
|
50
|
-
fresh Rails process, LSAPI dispatcher
|
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
|
64
|
-
runner under scripts/ folder. You need to configure
|
65
|
-
LSAPI application, then add a script handler
|
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
|
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 (
|
211
|
-
|
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
|
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
|
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
|
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
|
-
|
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 (
|
246
|
+
if ( s_req_processed < s_max_reqs )
|
212
247
|
{
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
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.
|
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:
|