iodine 0.2.3 → 0.2.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8757fa617add5c9d6d4c8b7feee4c3b97952a7e3
4
- data.tar.gz: b66b35b5662458733a47d5358901278e428811b3
3
+ metadata.gz: c5dd781b994de37f715d28a0bb3d2116d0130ec7
4
+ data.tar.gz: ef6e1fb31118a909c479c5b3a5eca55984794cfa
5
5
  SHA512:
6
- metadata.gz: 65bc4f93c07a4e81eacdc5ce203bf16516c079a246ca4aee6bec078e3180b0d9aebeb653c711a5519d45f57ab817a188ad1c2509bb87b2587c50ab7763155e4b
7
- data.tar.gz: ec57fa3e6674bb4393017f188671bf88ce851b6948b1c3b53917a5b78bef1b6822967e1b525e73250288e4d020a29aaa977f1167201ba22b3b12e300020070c7
6
+ metadata.gz: dcc16cec26d57a181e7883fef1772abff857f07c5d20ef7900f3ea1c63e953061567185d0456be14b6dfa8e827f7637720555455e38b5146ddcba26ca2d41eee
7
+ data.tar.gz: 1ca3bb3ccd3d45ad069e9093af6cecdd73c08ccb9b6018394f4ca1467cc7ae157cdcee248da32c5f5e82e91f5042a98d6173f10eeecf073225415c67bf9c7d97
@@ -8,9 +8,21 @@ Please notice that this change log contains changes for upcoming releases as wel
8
8
 
9
9
  ***
10
10
 
11
+ Change log v.0.2.4
12
+
13
+ **Minor Fix**: Patched Iodine against Apple's broken `getrlimit` on macOS. This allows correct auto-setting of open file limits for the socket layer.
14
+
15
+ **Minor Fix**: Fixed the processor under-utilization warning, where "0" might be shown for the number processes instead of "1".
16
+
17
+ **Update**: Added support for the `env` keys `HTTP_VERSION` and `SERVER_PROTOCOL` to indicate the HTTP protocol version. Iodine implements an HTTP/1.1 server, so versions aren't expected to be higher than 1.x.
18
+
19
+ **Update**: Iodine::Rack startup messages now include details regarding open file limits imposed by the OS (open file limits control the maximum allowed concurrent connections and other resource limits).
20
+
21
+ ***
22
+
11
23
  Change log v.0.2.3
12
24
 
13
- **Update** The `write` system call is now deferred when resources allow, meaning that (as long as the `write` buffer isn't full) `write` is not only non-blocking, but it's performed as a separate event, outside of the Ruby GIL.
25
+ **Update**: The `write` system call is now deferred when resources allow, meaning that (as long as the `write` buffer isn't full) `write` is not only non-blocking, but it's performed as a separate event, outside of the Ruby GIL.
14
26
 
15
27
  **Update**: The global socket `write` buffer was increased to ~16Mb (from ~4Mb), allowing for more concurrent `write` operations. However, the `write` buffer is still limited and `write` might block while the buffer is full. Blocking and "hanging" the server until there's enough room in the buffer for the requested `write` will slow the server down while keeping it healthy and more secure. IMHO, it is the lesser of two evils.
16
28
 
data/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  Iodine makes writing Object Oriented **Network Services** easy to write.
10
10
 
11
- Iodine is an **evented** framework with a simple API that builds off a low level [C code library](https://github.com/boazsegev/c-server-tools) with support for **epoll** and **kqueue** - this means that:
11
+ Iodine is an **evented** framework with a simple API that builds off the low level [C code library facil.io](https://github.com/boazsegev/facil.io) with support for **epoll** and **kqueue** - this means that:
12
12
 
13
13
  * Iodine can handle **thousands of concurrent connections** (tested with 20K connections).
14
14
 
@@ -352,7 +352,7 @@ Yes, please, here are some thoughts:
352
352
 
353
353
  * I'm really not good at writing automated tests and benchmarks, any help would be appreciated. I keep testing manually and that's less then ideal (and it's mistake prone).
354
354
 
355
- * If we can write a Java wrapper for [the C libraries](https://github.com/boazsegev/c-server-tools), it would be nice... but it could be as big a project as the whole gem, as a lot of minor details are implemented within the bridge between these two languages.
355
+ * If we can write a Java wrapper for [the C libraries](https://github.com/boazsegev/facil.io), it would be nice... but it could be as big a project as the whole gem, as a lot of minor details are implemented within the bridge between these two languages.
356
356
 
357
357
  * Bug reports and pull requests are welcome on GitHub at https://github.com/boazsegev/iodine.
358
358
 
@@ -380,7 +380,7 @@ Here's a few things you can use from this project and they seem to be handy to h
380
380
 
381
381
  I'm attaching it to one of Iodine's library classes, just in-case someone adopts my code and decides the registry should be owned by the global Object class.
382
382
 
383
- * I was using a POSIX thread pool library ([`libasync.h`](https://github.com/boazsegev/c-server-tools/blob/master/lib/libasync.c)) until I realized how many issues Ruby has with non-Ruby threads... So now there's a Ruby-thread port for this library at ([`rb-libasync.h`](https://github.com/boazsegev/iodine/blob/master/ext/iodine/rb-libasync.h)).
383
+ * I was using a POSIX thread pool library ([`libasync.h`](https://github.com/boazsegev/facil.io/blob/master/lib/libasync.c)) until I realized how many issues Ruby has with non-Ruby threads... So now there's a Ruby-thread port for this library at ([`rb-libasync.h`](https://github.com/boazsegev/iodine/blob/master/ext/iodine/rb-libasync.h)).
384
384
 
385
385
  Notice that all the new threads are free from the GVL - this allows true concurrency... but, you can't make Ruby API calls in that state.
386
386
 
@@ -16,9 +16,9 @@ The Websocket Callback Object should be a class (or an instance of such class) w
16
16
 
17
17
  * `on_message(data)` WILL be called when incoming Websocket data is received. `data` will be a String with an encoding of UTF-8 for text messages and `binary` encoding for non-text messages (as specified by the Websocket Protocol).
18
18
 
19
- The *client* **must** assume that the `data` String will be a **recyclable buffer** and that it's content will be corrupted the moment the `on_message` callback returns.
19
+ The *client* **MUST** assume that the `data` String will be a **recyclable buffer** and that it's content will be corrupted the moment the `on_message` callback returns.
20
20
 
21
- * `on_ready()` MAY be called when the state of the out-going socket buffer changes from full to not full (data can be sent to the socket). **If** `has_pending?` returns `true`, the `on_ready` callback **must** be called once the buffer state changes.
21
+ * `on_ready()` **MAY** be called when the state of the out-going socket buffer changes from full to not full (data can be sent to the socket). **If** `has_pending?` returns `true`, the `on_ready` callback **MUST** be called once the buffer state changes.
22
22
 
23
23
  * `on_shutdown()` MAY be called during the server's graceful shutdown process, _before_ the connection is closed and in addition to the `on_close` function (which is called _after_ the connection is closed.
24
24
 
@@ -28,15 +28,15 @@ The Websocket Callback Object should be a class (or an instance of such class) w
28
28
 
29
29
  The following method names are reserved for the network implementation: `write`, `close` and `has_pending?`.
30
30
 
31
- The server **must** extend the Websocket Callback Object's *class* using `extend`, so that the Websocket Callback Object inherits the following methods:
31
+ The server **MUST** extend the Websocket Callback Object's *class* using `extend`, so that the Websocket Callback Object inherits the following methods:
32
32
 
33
- * `write(data)` will attempt to send the data through the websocket connection. `data` **must** be a String. If `data` is UTF-8 encoded, the data will be sent as text. If `data` is binary encoded it will be sent as non-text (as specified by the Websocket Protocol).
33
+ * `write(data)` will attempt to send the data through the websocket connection. `data` **MUST** be a String. If `data` is UTF-8 encoded, the data will be sent as text. If `data` is binary encoded it will be sent as non-text (as specified by the Websocket Protocol).
34
34
 
35
35
  `write` has the same delivery promise as `Socket#write` (a successful `write` does **not** mean any of the data will reach the other side).
36
36
 
37
37
  `write` shall return `true` on success and `false` if the websocket is closed.
38
38
 
39
- A server **should** document whether `write` will block or return immediately. It is **recommended** that servers implement buffered IO, allowing `write` to return immediately when resources allow and block (or, possibly, disconnect) when the IO buffer is full.
39
+ A server **SHOULD** document whether `write` will block or return immediately. It is **RECOMMENDED** that servers implement buffered IO, allowing `write` to return immediately when resources allow and block (or, possibly, disconnect) when the IO buffer is full.
40
40
 
41
41
  * `close` closes the connection once all the data in the outgoing queue was sent. If `close` is called while there is still data to be sent, `close` will only take effect once the data was sent.
42
42
 
@@ -54,9 +54,9 @@ The following keywords (both as method names and instance variable names) are re
54
54
 
55
55
  * The `conn_id` object may be used as a connection ID for any functionality not specified herein.
56
56
 
57
- Connection `ping` / `pong`, timeouts and network considerations should be implemented by the server. It is **recommended** (but not required) that the server send `ping`s to prevent connection timeouts and detect network failure.
57
+ Connection `ping` / `pong`, timeouts and network considerations should be implemented by the server. It is **RECOMMENDED** (but not required) that the server send `ping`s to prevent connection timeouts and detect network failure.
58
58
 
59
- Server settings **may** (not required) be provided to allow for customization and adaptation for different network environments or websocket extensions. It is **recommended** that any settings be available as command line arguments and **not** incorporated into the application's logic.
59
+ Server settings **MAY** (not required) be provided to allow for customization and adaptation for different network environments or websocket extensions. It is **RECOMMENDED** that any settings be available as command line arguments and **not** incorporated into the application's logic.
60
60
 
61
61
  ## Upgrading
62
62
 
@@ -566,7 +566,7 @@ static void *srv_start_no_gvl(void *_) {
566
566
  "utilizing %lu processes.\n - %s\n"
567
567
  " - Use the command line option: `-w %lu`\n"
568
568
  " - Or, within Ruby: `Iodine.processes = %lu`\n",
569
- cpu_count, processes,
569
+ cpu_count, (processes ? processes : 1),
570
570
  (processes < cpu_count
571
571
  ? "Some CPUs won't be utilized, inhibiting performance."
572
572
  : "This causes excessive context switches, wasting resources."),
@@ -43,6 +43,9 @@ rack_declare(QUERY_STRING);
43
43
  rack_declare(QUERY_ESTRING);
44
44
  rack_declare(SERVER_NAME);
45
45
  rack_declare(SERVER_PORT);
46
+ rack_declare(SERVER_PROTOCOL);
47
+ rack_declare(HTTP_VERSION);
48
+ rack_declare(REMOTE_ADDR);
46
49
  rack_declare(CONTENT_LENGTH);
47
50
  rack_declare(CONTENT_TYPE);
48
51
  rack_declare(R_URL_SCHEME); // rack.url_scheme
@@ -78,6 +81,18 @@ static inline VALUE copy2env(http_request_s *request) {
78
81
  (request->query
79
82
  ? rb_enc_str_new(request->query, request->query_len, BinaryEncoding)
80
83
  : QUERY_ESTRING));
84
+ rb_hash_aset(
85
+ env, QUERY_STRING,
86
+ (request->query
87
+ ? rb_enc_str_new(request->query, request->query_len, BinaryEncoding)
88
+ : QUERY_ESTRING));
89
+
90
+ hname =
91
+ rb_enc_str_new(request->version, request->version_len, BinaryEncoding);
92
+ rb_hash_aset(env, SERVER_PROTOCOL, hname);
93
+ rb_hash_aset(env, HTTP_VERSION, hname);
94
+
95
+ // rack_declare(REMOTE_ADDR);
81
96
 
82
97
  /* setup input IO + hijack support */
83
98
  rb_hash_aset(env, R_INPUT, (hname = RackIO.new(request, env)));
@@ -539,16 +554,21 @@ int iodine_http_review(void) {
539
554
  fprintf(stderr, "Starting up Iodine Http Server:\n"
540
555
  " * Ruby v.%s\n * Iodine v.%s \n"
541
556
  " * %d processes X %d thread%s\n"
557
+ " * %d max concurrent connections / open files\n"
542
558
  " * Serving static files from:\n"
543
559
  " %s\n\n",
544
560
  StringValueCStr(ruby_version), StringValueCStr(iodine_version),
545
- processes, threads, (threads > 1 ? "s" : ""), public_folder);
561
+ processes, threads, (threads > 1 ? "s" : ""), sock_max_capacity(),
562
+ public_folder);
546
563
  else
547
564
  fprintf(stderr, "Starting up Iodine Http Server:\n"
548
565
  " * Ruby v.%s\n * Iodine v.%s \n"
549
- " * %d processes X %d thread%s\n\n",
566
+ " * %d processes X %d thread%s\n"
567
+ " * %d max concurrent connections / open files\n"
568
+ "\n",
550
569
  StringValueCStr(ruby_version), StringValueCStr(iodine_version),
551
- processes, threads, (threads > 1 ? "s" : ""));
570
+ processes, threads, (threads > 1 ? "s" : ""),
571
+ sock_max_capacity());
552
572
 
553
573
  // listen
554
574
  return http1_listen(port, address, .on_request = on_rack_request,
@@ -571,6 +591,9 @@ void Init_iodine_http(void) {
571
591
  rack_autoset(SERVER_PORT);
572
592
  rack_autoset(CONTENT_LENGTH);
573
593
  rack_autoset(CONTENT_TYPE);
594
+ rack_autoset(SERVER_PROTOCOL);
595
+ rack_autoset(HTTP_VERSION);
596
+ rack_autoset(REMOTE_ADDR);
574
597
  rack_set(HTTP_SCHEME, "http");
575
598
  rack_set(HTTPS_SCHEME, "https");
576
599
  rack_set(QUERY_ESTRING, "");
@@ -10,17 +10,18 @@ Feel free to copy, use and enjoy according to the license provided.
10
10
 
11
11
  #include "libsock.h"
12
12
 
13
- #include <string.h>
14
- #include <stdio.h>
15
- #include <time.h>
16
- #include <fcntl.h>
17
13
  #include <errno.h>
14
+ #include <fcntl.h>
15
+ #include <limits.h>
18
16
  #include <netdb.h>
19
- #include <sys/types.h>
20
- #include <sys/socket.h>
17
+ #include <stdio.h>
18
+ #include <string.h>
21
19
  #include <sys/mman.h>
22
- #include <sys/time.h>
23
20
  #include <sys/resource.h>
21
+ #include <sys/socket.h>
22
+ #include <sys/time.h>
23
+ #include <sys/types.h>
24
+ #include <time.h>
24
25
 
25
26
  /* *****************************************************************************
26
27
  Use spinlocks "spnlock.h".
@@ -62,7 +63,7 @@ OS Sendfile settings.
62
63
  #elif defined(__unix__) /* BSD sendfile should work, but isn't tested */
63
64
  #include <sys/uio.h>
64
65
  #define USE_SENDFILE 0
65
- #elif defined(__APPLE__) /* AIs the pple sendfile still broken? */
66
+ #elif defined(__APPLE__) /* Is the apple sendfile still broken? */
66
67
  #include <sys/uio.h>
67
68
  #define USE_SENDFILE 1
68
69
  #else /* sendfile might not be available - always set to 0 */
@@ -130,11 +131,16 @@ ssize_t sock_max_capacity(void) {
130
131
  flim = OPEN_MAX;
131
132
  #endif
132
133
  // try to maximize limits - collect max and set to max
133
- struct rlimit rlim;
134
+ struct rlimit rlim = {0};
134
135
  getrlimit(RLIMIT_NOFILE, &rlim);
135
- // printf("Meximum open files are %llu out of %llu\n", rlim.rlim_cur,
136
- // rlim.rlim_max);
136
+ // printf("Meximum open files are %llu out of %llu\n", rlim.rlim_cur,
137
+ // rlim.rlim_max);
138
+ #if defined(__APPLE__) /* Apple's getrlimit is broken. */
139
+ rlim.rlim_cur = rlim.rlim_max >= OPEN_MAX ? OPEN_MAX : rlim.rlim_max;
140
+ #else
137
141
  rlim.rlim_cur = rlim.rlim_max;
142
+ #endif
143
+
138
144
  setrlimit(RLIMIT_NOFILE, &rlim);
139
145
  getrlimit(RLIMIT_NOFILE, &rlim);
140
146
  // printf("Meximum open files are %llu out of %llu\n", rlim.rlim_cur,
@@ -233,9 +239,9 @@ Call this function before calling any `libsock` functions.
233
239
  static void destroy_lib_data(void) {
234
240
  if (fd_info) {
235
241
  while (fd_capacity--) { // include 0 in countdown
236
- if (fd_info[fd_capacity].open) {
237
- fprintf(stderr, "Socket %lu is marked as open\n", fd_capacity);
238
- }
242
+ // if (fd_info[fd_capacity].open) {
243
+ // fprintf(stderr, "Socket %lu is marked as open\n", fd_capacity);
244
+ // }
239
245
  set_fd(fd_capacity, LIB_SOCK_STATE_CLOSED);
240
246
  }
241
247
  #if USE_MALLOC == 1
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '0.2.3'.freeze
2
+ VERSION = '0.2.4'.freeze
3
3
  end
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.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-10-07 00:00:00.000000000 Z
11
+ date: 2016-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -200,7 +200,7 @@ requirements:
200
200
  - Ruby >= 2.2.2
201
201
  - Ruby >= 2.0.0 is recommended.
202
202
  rubyforge_project:
203
- rubygems_version: 2.5.1
203
+ rubygems_version: 2.5.2
204
204
  signing_key:
205
205
  specification_version: 4
206
206
  summary: Iodine - leveraging C for Ruby servers.