iodine 0.7.27 → 0.7.28
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +2 -0
- data/ext/iodine/fio.h +28 -20
- data/ext/iodine/iodine_caller.c +34 -1
- data/ext/iodine/iodine_caller.h +4 -0
- data/ext/iodine/iodine_defer.c +2 -0
- data/ext/iodine/iodine_http.c +6 -3
- data/lib/iodine/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b76690963cd5e669bee41bd2859f60164c3a9ce4dbcc56706864fe05ce5db049
|
4
|
+
data.tar.gz: cebe9da9b5206d2229e1ecefac594c26ffb548e0ff25aefba5429f0724e8a97f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9799ff98973047f253fafedcb3f5dc70b2e7f04409c0eb415093e1d984eea3996f6b2cd7ee2dc87fbdacd94653a95299857f4bae5146188c91e9a656add6b36
|
7
|
+
data.tar.gz: f422ac357af80a1a60a5ffe4940cf25afce4132aae41aae9f94048f8e6250e43b1d0aca09bedf4f9dbc1e7f733f5b7c6c3fab12d5fe4ef6cbaa48d4923196554
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,10 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
6
6
|
|
7
7
|
## Changes:
|
8
8
|
|
9
|
+
#### Change log v.0.7.28
|
10
|
+
|
11
|
+
**Fix**: fixed an issue where iodine would crush (or hang) if unprotected exceptions were raised within a response body's `each` loop. This also fixes Fiber support when streaming with Roda (note: iodine will concat the body in a buffer before sending it). Credit to @adam12 (Adam Daniels) both for exposing the issue (#70) and testing possible solutions.
|
12
|
+
|
9
13
|
#### Change log v.0.7.27
|
10
14
|
|
11
15
|
**Compatibility**: (`iodine`) fixed the HTTP request `SCRIPT_NAME` variable (in the Rack `env`) to default to the global environment variable `SCRIPT_NAME` when `SCRIPT_NAME` isn't root (`/`). Credit to @thexa4 (Max Maton) for exposing this compatibility concern (issue #68).
|
data/README.md
CHANGED
@@ -36,6 +36,8 @@ Iodine is an **evented** framework with a simple API that ports much of the [C f
|
|
36
36
|
|
37
37
|
Iodine is a C extension for Ruby, developed and optimized for Ruby MRI 2.2.2 and up... it should support the whole Ruby 2.0 MRI family, but CI tests start at Ruby 2.2.2.
|
38
38
|
|
39
|
+
**Note**: iodine does **not** support the streaming when using Rack. Streaming over Rack should be avoided on any server, WebSockets, SSE and `Range` requests should always be preferred. On iodine no data will be sent before the whole of the data is available.
|
40
|
+
|
39
41
|
## Iodine - a fast & powerful HTTP + Websockets server with native Pub/Sub
|
40
42
|
|
41
43
|
Iodine includes a light and fast HTTP and Websocket server written in C that was written according to the [Rack interface specifications](http://www.rubydoc.info/github/rack/rack/master/file/SPEC) and the [Websocket draft extension](./SPEC-Websocket-Draft.md).
|
data/ext/iodine/fio.h
CHANGED
@@ -423,35 +423,43 @@ Logging and testing helpers
|
|
423
423
|
#define FIO_LOG_LEVEL_DEBUG 5
|
424
424
|
|
425
425
|
#if FIO_LOG_LENGTH_LIMIT > 128
|
426
|
-
#define
|
427
|
-
#define
|
426
|
+
#define FIO_LOG____LENGTH_ON_STACK FIO_LOG_LENGTH_LIMIT
|
427
|
+
#define FIO_LOG____LENGTH_BORDER (FIO_LOG_LENGTH_LIMIT - 32)
|
428
428
|
#else
|
429
|
-
#define
|
430
|
-
#define
|
429
|
+
#define FIO_LOG____LENGTH_ON_STACK (FIO_LOG_LENGTH_LIMIT + 32)
|
430
|
+
#define FIO_LOG____LENGTH_BORDER FIO_LOG_LENGTH_LIMIT
|
431
431
|
#endif
|
432
432
|
/** The logging level */
|
433
433
|
int __attribute__((weak)) FIO_LOG_LEVEL;
|
434
434
|
|
435
|
+
#pragma weak FIO_LOG2STDERR
|
436
|
+
void __attribute__((format(printf, 1, 0), weak))
|
437
|
+
FIO_LOG2STDERR(const char *format, ...) {
|
438
|
+
char tmp___log[FIO_LOG____LENGTH_ON_STACK];
|
439
|
+
va_list argv;
|
440
|
+
va_start(argv, format);
|
441
|
+
int len___log = vsnprintf(tmp___log, FIO_LOG_LENGTH_LIMIT - 2, format, argv);
|
442
|
+
va_end(argv);
|
443
|
+
if (len___log <= 0 || len___log >= FIO_LOG_LENGTH_LIMIT - 2) {
|
444
|
+
if (len___log >= FIO_LOG_LENGTH_LIMIT - 2) {
|
445
|
+
memcpy(tmp___log + FIO_LOG____LENGTH_BORDER, "... (warning: truncated).",
|
446
|
+
25);
|
447
|
+
len___log = FIO_LOG____LENGTH_BORDER + 25;
|
448
|
+
} else {
|
449
|
+
fwrite("ERROR: log output error (can't write).\n", 39, 1, stderr);
|
450
|
+
return;
|
451
|
+
}
|
452
|
+
}
|
453
|
+
tmp___log[len___log++] = '\n';
|
454
|
+
tmp___log[len___log] = '0';
|
455
|
+
fwrite(tmp___log, len___log, 1, stderr);
|
456
|
+
}
|
457
|
+
|
435
458
|
#ifndef FIO_LOG_PRINT
|
436
459
|
#define FIO_LOG_PRINT(level, ...) \
|
437
460
|
do { \
|
438
461
|
if (level <= FIO_LOG_LEVEL) { \
|
439
|
-
|
440
|
-
int len___log = \
|
441
|
-
snprintf(tmp___log, FIO_LOG_LENGTH_LIMIT - 2, __VA_ARGS__); \
|
442
|
-
if (len___log <= 0 || len___log >= FIO_LOG_LENGTH_LIMIT - 2) { \
|
443
|
-
if (len___log >= FIO_LOG_LENGTH_LIMIT - 2) { \
|
444
|
-
memcpy(tmp___log + FIO_LOG_LENGTH_BORDER, \
|
445
|
-
"... (warning: truncated).", 25); \
|
446
|
-
len___log = FIO_LOG_LENGTH_BORDER + 25; \
|
447
|
-
} else { \
|
448
|
-
fwrite("ERROR: log output error (can't write).\n", 39, 1, stderr); \
|
449
|
-
break; \
|
450
|
-
} \
|
451
|
-
} \
|
452
|
-
tmp___log[len___log++] = '\n'; \
|
453
|
-
tmp___log[len___log] = '0'; \
|
454
|
-
fwrite(tmp___log, len___log, 1, stderr); \
|
462
|
+
FIO_LOG2STDERR(__VA_ARGS__); \
|
455
463
|
} \
|
456
464
|
} while (0)
|
457
465
|
#define FIO_LOG_DEBUG(...) \
|
data/ext/iodine/iodine_caller.c
CHANGED
@@ -18,6 +18,9 @@ typedef struct {
|
|
18
18
|
VALUE *argv;
|
19
19
|
ID method;
|
20
20
|
int exception;
|
21
|
+
VALUE (*protected_task)(VALUE tsk_);
|
22
|
+
VALUE (*each_func)(VALUE block_arg, VALUE data, int argc, VALUE *argv);
|
23
|
+
VALUE each_udata;
|
21
24
|
} iodine_rb_task_s;
|
22
25
|
|
23
26
|
/* printout backtrace in case of exceptions */
|
@@ -47,6 +50,13 @@ static void *iodine_handle_exception(void *ignr) {
|
|
47
50
|
return (void *)Qnil;
|
48
51
|
}
|
49
52
|
|
53
|
+
/* calls the Ruby each method within the protection block */
|
54
|
+
static VALUE iodine_ruby_caller_perform_block(VALUE tsk_) {
|
55
|
+
iodine_rb_task_s *task = (void *)tsk_;
|
56
|
+
return rb_block_call(task->obj, task->method, task->argc, task->argv,
|
57
|
+
task->each_func, task->each_udata);
|
58
|
+
}
|
59
|
+
|
50
60
|
/* calls the Ruby method within the protection block */
|
51
61
|
static VALUE iodine_ruby_caller_perform(VALUE tsk_) {
|
52
62
|
iodine_rb_task_s *task = (void *)tsk_;
|
@@ -56,7 +66,8 @@ static VALUE iodine_ruby_caller_perform(VALUE tsk_) {
|
|
56
66
|
/* wrap the function call in exception handling block (uses longjmp) */
|
57
67
|
static void *iodine_protect_ruby_call(void *task_) {
|
58
68
|
int state = 0;
|
59
|
-
VALUE ret = rb_protect(
|
69
|
+
VALUE ret = rb_protect(((iodine_rb_task_s *)task_)->protected_task,
|
70
|
+
(VALUE)(task_), &state);
|
60
71
|
if (state) {
|
61
72
|
iodine_handle_exception(NULL);
|
62
73
|
}
|
@@ -98,6 +109,7 @@ static VALUE iodine_call(VALUE obj, ID method) {
|
|
98
109
|
.argc = 0,
|
99
110
|
.argv = NULL,
|
100
111
|
.method = method,
|
112
|
+
.protected_task = iodine_ruby_caller_perform,
|
101
113
|
};
|
102
114
|
void *rv = iodine_enterGVL(iodine_protect_ruby_call, &task);
|
103
115
|
return (VALUE)rv;
|
@@ -110,6 +122,25 @@ static VALUE iodine_call2(VALUE obj, ID method, int argc, VALUE *argv) {
|
|
110
122
|
.argc = argc,
|
111
123
|
.argv = argv,
|
112
124
|
.method = method,
|
125
|
+
.protected_task = iodine_ruby_caller_perform,
|
126
|
+
};
|
127
|
+
void *rv = iodine_enterGVL(iodine_protect_ruby_call, &task);
|
128
|
+
return (VALUE)rv;
|
129
|
+
}
|
130
|
+
|
131
|
+
/** Calls a Ruby method on a given object, protecting against exceptions. */
|
132
|
+
static VALUE iodine_call_block(VALUE obj, ID method, int argc, VALUE *argv,
|
133
|
+
VALUE udata,
|
134
|
+
VALUE(each_func)(VALUE block_arg, VALUE udata,
|
135
|
+
int argc, VALUE *argv)) {
|
136
|
+
iodine_rb_task_s task = {
|
137
|
+
.obj = obj,
|
138
|
+
.argc = argc,
|
139
|
+
.argv = argv,
|
140
|
+
.method = method,
|
141
|
+
.protected_task = iodine_ruby_caller_perform_block,
|
142
|
+
.each_func = each_func,
|
143
|
+
.each_udata = udata,
|
113
144
|
};
|
114
145
|
void *rv = iodine_enterGVL(iodine_protect_ruby_call, &task);
|
115
146
|
return (VALUE)rv;
|
@@ -131,6 +162,8 @@ struct IodineCaller_s IodineCaller = {
|
|
131
162
|
/** Calls a C function outside the GVL. */
|
132
163
|
.leaveGVL = iodine_leaveGVL,
|
133
164
|
/** Calls a Ruby method on a given object, protecting against exceptions. */
|
165
|
+
.call_with_block = iodine_call_block,
|
166
|
+
/** Calls a Ruby method on a given object, protecting against exceptions. */
|
134
167
|
.call = iodine_call,
|
135
168
|
/** Calls a Ruby method on a given object, protecting against exceptions. */
|
136
169
|
.call2 = iodine_call2,
|
data/ext/iodine/iodine_caller.h
CHANGED
@@ -14,6 +14,10 @@ extern struct IodineCaller_s {
|
|
14
14
|
VALUE (*call)(VALUE obj, ID method);
|
15
15
|
/** Calls a Ruby method on a given object, protecting against exceptions. */
|
16
16
|
VALUE (*call2)(VALUE obj, ID method, int argc, VALUE *argv);
|
17
|
+
/** Calls a Ruby method on a given object, protecting against exceptions. */
|
18
|
+
VALUE(*call_with_block)
|
19
|
+
(VALUE obj, ID method, int argc, VALUE *argv, VALUE udata,
|
20
|
+
VALUE (*block_func)(VALUE block_argv1, VALUE udata, int argc, VALUE *argv));
|
17
21
|
/** Returns the GVL state flag. */
|
18
22
|
uint8_t (*in_GVL)(void);
|
19
23
|
/** Forces the GVL state flag. */
|
data/ext/iodine/iodine_defer.c
CHANGED
@@ -414,4 +414,6 @@ void iodine_defer_initialize(void) {
|
|
414
414
|
fio_state_callback_add(FIO_CALL_ON_START, iodine_start_io_thread, NULL);
|
415
415
|
/* stop the IO thread before exit */
|
416
416
|
fio_state_callback_add(FIO_CALL_ON_FINISH, iodine_defer_on_finish, NULL);
|
417
|
+
/* kill IO thread even after a non-graceful iodine shutdown (force-quit) */
|
418
|
+
fio_state_callback_add(FIO_CALL_AT_EXIT, iodine_defer_on_finish, NULL);
|
417
419
|
}
|
data/ext/iodine/iodine_http.c
CHANGED
@@ -514,7 +514,8 @@ static int for_each_header_data(VALUE key, VALUE val, VALUE h_) {
|
|
514
514
|
}
|
515
515
|
|
516
516
|
// writes the body to the response object
|
517
|
-
static VALUE for_each_body_string(VALUE str, VALUE body_
|
517
|
+
static VALUE for_each_body_string(VALUE str, VALUE body_, int argc,
|
518
|
+
VALUE *argv) {
|
518
519
|
// fprintf(stderr, "For_each - body\n");
|
519
520
|
// write body
|
520
521
|
if (TYPE(str) != T_STRING) {
|
@@ -525,6 +526,8 @@ static VALUE for_each_body_string(VALUE str, VALUE body_) {
|
|
525
526
|
fiobj_str_write((FIOBJ)body_, RSTRING_PTR(str), RSTRING_LEN(str));
|
526
527
|
}
|
527
528
|
return Qtrue;
|
529
|
+
(void)argc;
|
530
|
+
(void)argv;
|
528
531
|
}
|
529
532
|
|
530
533
|
static inline int ruby2c_response_send(iodine_http_request_handle_s *handle,
|
@@ -559,8 +562,8 @@ static inline int ruby2c_response_send(iodine_http_request_handle_s *handle,
|
|
559
562
|
// fprintf(stderr, "Review body as for-each ...\n");
|
560
563
|
handle->body = fiobj_str_buf(1);
|
561
564
|
handle->type = IODINE_HTTP_SENDBODY;
|
562
|
-
|
563
|
-
|
565
|
+
IodineCaller.call_with_block(body, each_method_id, 0, NULL,
|
566
|
+
(VALUE)handle->body, for_each_body_string);
|
564
567
|
// we need to call `close` in case the object is an IO / BodyProxy
|
565
568
|
if (rb_respond_to(body, close_method_id))
|
566
569
|
IodineCaller.call(body, close_method_id);
|
data/lib/iodine/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iodine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boaz Segev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-03-
|
11
|
+
date: 2019-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -202,7 +202,7 @@ licenses:
|
|
202
202
|
- MIT
|
203
203
|
metadata:
|
204
204
|
allowed_push_host: https://rubygems.org
|
205
|
-
post_install_message: 'Thank you for installing Iodine 0.7.
|
205
|
+
post_install_message: 'Thank you for installing Iodine 0.7.28.
|
206
206
|
|
207
207
|
'
|
208
208
|
rdoc_options: []
|