noderb 0.0.8 → 0.0.9

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.
Files changed (84) hide show
  1. data/ext/noderb_extension/extconf.rb +4 -2
  2. data/ext/noderb_extension/libuv/AUTHORS +2 -0
  3. data/ext/noderb_extension/libuv/Makefile +1 -1
  4. data/ext/noderb_extension/libuv/common.gypi +51 -51
  5. data/ext/noderb_extension/libuv/config-mingw.mk +3 -9
  6. data/ext/noderb_extension/libuv/config-unix.mk +10 -1
  7. data/ext/noderb_extension/libuv/include/uv-private/uv-unix.h +3 -2
  8. data/ext/noderb_extension/libuv/include/uv-private/uv-win.h +7 -6
  9. data/ext/noderb_extension/libuv/include/uv.h +47 -13
  10. data/ext/noderb_extension/libuv/src/ares/config_netbsd/ares_config.h +510 -0
  11. data/ext/noderb_extension/libuv/src/unix/core.c +20 -65
  12. data/ext/noderb_extension/libuv/src/unix/darwin.c +1 -0
  13. data/ext/noderb_extension/libuv/src/unix/eio/config_netbsd.h +81 -0
  14. data/ext/noderb_extension/libuv/src/unix/error.c +9 -1
  15. data/ext/noderb_extension/libuv/src/unix/ev/config_netbsd.h +120 -0
  16. data/ext/noderb_extension/libuv/src/unix/fs.c +151 -21
  17. data/ext/noderb_extension/libuv/src/unix/internal.h +30 -0
  18. data/ext/noderb_extension/libuv/src/unix/netbsd.c +68 -0
  19. data/ext/noderb_extension/libuv/src/unix/pipe.c +20 -30
  20. data/ext/noderb_extension/libuv/src/unix/process.c +13 -0
  21. data/ext/noderb_extension/libuv/src/unix/stream.c +105 -63
  22. data/ext/noderb_extension/libuv/src/unix/tcp.c +75 -21
  23. data/ext/noderb_extension/libuv/src/unix/tty.c +69 -0
  24. data/ext/noderb_extension/libuv/src/unix/udp.c +31 -0
  25. data/ext/noderb_extension/libuv/src/uv-common.c +2 -0
  26. data/ext/noderb_extension/libuv/src/uv-common.h +0 -6
  27. data/ext/noderb_extension/libuv/src/win/cares.c +7 -7
  28. data/ext/noderb_extension/libuv/src/win/core.c +25 -17
  29. data/ext/noderb_extension/libuv/src/win/error.c +7 -0
  30. data/ext/noderb_extension/libuv/src/win/fs.c +587 -92
  31. data/ext/noderb_extension/libuv/src/win/getaddrinfo.c +3 -1
  32. data/ext/noderb_extension/libuv/src/win/handle.c +0 -17
  33. data/ext/noderb_extension/libuv/src/win/internal.h +15 -5
  34. data/ext/noderb_extension/libuv/src/win/loop-watcher.c +1 -1
  35. data/ext/noderb_extension/libuv/src/win/pipe.c +6 -0
  36. data/ext/noderb_extension/libuv/src/win/process.c +90 -43
  37. data/ext/noderb_extension/libuv/src/win/tcp.c +37 -4
  38. data/ext/noderb_extension/libuv/src/win/threads.c +81 -0
  39. data/ext/noderb_extension/libuv/src/win/timer.c +15 -15
  40. data/ext/noderb_extension/libuv/src/win/tty.c +37 -0
  41. data/ext/noderb_extension/libuv/src/win/udp.c +8 -2
  42. data/ext/noderb_extension/libuv/src/win/winapi.c +12 -0
  43. data/ext/noderb_extension/libuv/src/win/winapi.h +1146 -1015
  44. data/ext/noderb_extension/libuv/test/benchmark-ares.c +0 -1
  45. data/ext/noderb_extension/libuv/test/benchmark-getaddrinfo.c +0 -1
  46. data/ext/noderb_extension/libuv/test/benchmark-ping-pongs.c +0 -1
  47. data/ext/noderb_extension/libuv/test/benchmark-pound.c +0 -1
  48. data/ext/noderb_extension/libuv/test/benchmark-pump.c +4 -6
  49. data/ext/noderb_extension/libuv/test/benchmark-spawn.c +0 -1
  50. data/ext/noderb_extension/libuv/test/benchmark-udp-packet-storm.c +0 -1
  51. data/ext/noderb_extension/libuv/test/dns-server.c +2 -2
  52. data/ext/noderb_extension/libuv/test/echo-server.c +4 -5
  53. data/ext/noderb_extension/libuv/test/run-tests.c +0 -2
  54. data/ext/noderb_extension/libuv/test/test-async.c +0 -2
  55. data/ext/noderb_extension/libuv/test/test-callback-stack.c +0 -2
  56. data/ext/noderb_extension/libuv/test/test-connection-fail.c +3 -5
  57. data/ext/noderb_extension/libuv/test/test-delayed-accept.c +2 -3
  58. data/ext/noderb_extension/libuv/test/test-fs.c +578 -42
  59. data/ext/noderb_extension/libuv/test/test-get-currentexe.c +12 -2
  60. data/ext/noderb_extension/libuv/test/test-getaddrinfo.c +10 -5
  61. data/ext/noderb_extension/libuv/test/test-gethostbyname.c +0 -2
  62. data/ext/noderb_extension/libuv/test/test-getsockname.c +92 -72
  63. data/ext/noderb_extension/libuv/test/test-idle.c +0 -3
  64. data/ext/noderb_extension/libuv/test/test-list.h +13 -0
  65. data/ext/noderb_extension/libuv/test/test-loop-handles.c +0 -3
  66. data/ext/noderb_extension/libuv/test/test-ping-pong.c +13 -19
  67. data/ext/noderb_extension/libuv/test/test-pipe-bind-error.c +0 -12
  68. data/ext/noderb_extension/libuv/test/test-ref.c +0 -7
  69. data/ext/noderb_extension/libuv/test/test-shutdown-eof.c +3 -3
  70. data/ext/noderb_extension/libuv/test/test-spawn.c +2 -11
  71. data/ext/noderb_extension/libuv/test/test-tcp-bind-error.c +0 -19
  72. data/ext/noderb_extension/libuv/test/test-tcp-bind6-error.c +0 -15
  73. data/ext/noderb_extension/libuv/test/test-tcp-close.c +129 -0
  74. data/ext/noderb_extension/libuv/test/test-tcp-writealot.c +0 -3
  75. data/ext/noderb_extension/libuv/test/test-threadpool.c +0 -2
  76. data/ext/noderb_extension/libuv/test/test-timer-again.c +0 -3
  77. data/ext/noderb_extension/libuv/test/test-timer.c +0 -2
  78. data/ext/noderb_extension/libuv/test/test-udp-dgram-too-big.c +0 -2
  79. data/ext/noderb_extension/libuv/test/test-udp-ipv6.c +0 -2
  80. data/ext/noderb_extension/libuv/test/test-udp-send-and-recv.c +0 -2
  81. data/ext/noderb_extension/libuv/uv.gyp +18 -2
  82. data/ext/noderb_extension/noderb_fs.c +1 -2
  83. data/lib/noderb/version.rb +1 -1
  84. metadata +10 -2
@@ -25,6 +25,32 @@
25
25
  #include "uv-common.h"
26
26
  #include "uv-eio.h"
27
27
 
28
+ #if defined(__linux__)
29
+
30
+ #include <linux/version.h>
31
+ #include <features.h>
32
+
33
+ #undef HAVE_FUTIMES
34
+ #undef HAVE_PIPE2
35
+ #undef HAVE_ACCEPT4
36
+
37
+ /* futimes() requires linux >= 2.6.22 and glib >= 2.6 */
38
+ #if LINUX_VERSION_CODE >= 0x20616 && __GLIBC_PREREQ(2, 6)
39
+ #define HAVE_FUTIMES
40
+ #endif
41
+
42
+ /* pipe2() requires linux >= 2.6.27 and glibc >= 2.9 */
43
+ #if LINUX_VERSION_CODE >= 0x2061B && __GLIBC_PREREQ(2, 9)
44
+ #define HAVE_PIPE2
45
+ #endif
46
+
47
+ /* accept4() requires linux >= 2.6.28 and glib >= 2.10 */
48
+ #if LINUX_VERSION_CODE >= 0x2061C && __GLIBC_PREREQ(2, 10)
49
+ #define HAVE_ACCEPT4
50
+ #endif
51
+
52
+ #endif /* __linux__ */
53
+
28
54
  /* flags */
29
55
  enum {
30
56
  UV_CLOSING = 0x00000001, /* uv_close() called but not finished. */
@@ -48,12 +74,16 @@ int uv__cloexec(int fd, int set) __attribute__((unused));
48
74
  int uv__socket(int domain, int type, int protocol);
49
75
 
50
76
  /* error */
77
+ uv_err_code uv_translate_sys_error(int sys_errno);
51
78
  uv_err_t uv_err_new(uv_loop_t* loop, int sys_error);
52
79
  uv_err_t uv_err_new_artificial(uv_loop_t* loop, int code);
53
80
  void uv_fatal_error(const int errorno, const char* syscall);
54
81
 
55
82
  /* stream */
83
+ void uv__stream_init(uv_loop_t* loop, uv_stream_t* stream,
84
+ uv_handle_type type);
56
85
  int uv__stream_open(uv_stream_t*, int fd, int flags);
86
+ void uv__stream_destroy(uv_stream_t* stream);
57
87
  void uv__stream_io(EV_P_ ev_io* watcher, int revents);
58
88
  void uv__server_io(EV_P_ ev_io* watcher, int revents);
59
89
  int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t len);
@@ -0,0 +1,68 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
3
+ * of this software and associated documentation files (the "Software"), to
4
+ * deal in the Software without restriction, including without limitation the
5
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6
+ * sell copies of the Software, and to permit persons to whom the Software is
7
+ * furnished to do so, subject to the following conditions:
8
+ *
9
+ * The above copyright notice and this permission notice shall be included in
10
+ * all copies or substantial portions of the Software.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18
+ * IN THE SOFTWARE.
19
+ */
20
+
21
+ #include "uv.h"
22
+
23
+ #include <string.h>
24
+ #include <time.h>
25
+
26
+ #include <sys/types.h>
27
+ #include <sys/sysctl.h>
28
+
29
+ #include <unistd.h>
30
+
31
+ #undef NANOSEC
32
+ #define NANOSEC 1000000000
33
+
34
+ uint64_t uv_hrtime(void) {
35
+ struct timespec ts;
36
+ clock_gettime(CLOCK_MONOTONIC, &ts);
37
+ return (ts.tv_sec * NANOSEC + ts.tv_nsec);
38
+ }
39
+
40
+
41
+ int uv_exepath(char* buffer, size_t* size) {
42
+ uint32_t usize;
43
+ int result;
44
+ char* path;
45
+ char* fullpath;
46
+ int mib[4];
47
+ size_t cb;
48
+ pid_t mypid;
49
+
50
+ if (!buffer || !size) {
51
+ return -1;
52
+ }
53
+
54
+ mypid = getpid();
55
+ mib[0] = CTL_KERN;
56
+ mib[1] = KERN_PROC_ARGS;
57
+ mib[2] = mypid;
58
+ mib[3] = KERN_PROC_ARGV;
59
+
60
+ cb = *size;
61
+ if (sysctl(mib, 4, buffer, &cb, NULL, 0) < 0) {
62
+ *size = 0;
63
+ return -1;
64
+ }
65
+ *size = strlen(buffer);
66
+
67
+ return 0;
68
+ }
@@ -30,30 +30,15 @@
30
30
  #include <stdlib.h>
31
31
 
32
32
  int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle) {
33
- memset(handle, 0, sizeof *handle);
34
-
35
- uv__handle_init(loop, (uv_handle_t*)handle, UV_NAMED_PIPE);
33
+ uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
36
34
  loop->counters.pipe_init++;
37
-
38
- handle->type = UV_NAMED_PIPE;
39
- handle->pipe_fname = NULL; /* Only set by listener. */
40
-
41
- ev_init(&handle->write_watcher, uv__stream_io);
42
- ev_init(&handle->read_watcher, uv__stream_io);
43
- handle->write_watcher.data = handle;
44
- handle->read_watcher.data = handle;
45
- handle->accepted_fd = -1;
46
- handle->fd = -1;
47
-
48
- ngx_queue_init(&handle->write_completed_queue);
49
- ngx_queue_init(&handle->write_queue);
50
-
35
+ handle->pipe_fname = NULL;
51
36
  return 0;
52
37
  }
53
38
 
54
39
 
55
40
  int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
56
- struct sockaddr_un sun;
41
+ struct sockaddr_un saddr;
57
42
  const char* pipe_fname;
58
43
  int saved_errno;
59
44
  int sockfd;
@@ -86,11 +71,11 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
86
71
  goto out;
87
72
  }
88
73
 
89
- memset(&sun, 0, sizeof sun);
90
- uv__strlcpy(sun.sun_path, pipe_fname, sizeof(sun.sun_path));
91
- sun.sun_family = AF_UNIX;
74
+ memset(&saddr, 0, sizeof saddr);
75
+ uv__strlcpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path));
76
+ saddr.sun_family = AF_UNIX;
92
77
 
93
- if (bind(sockfd, (struct sockaddr*)&sun, sizeof sun) == -1) {
78
+ if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr) == -1) {
94
79
  /* On EADDRINUSE:
95
80
  *
96
81
  * We hold the file lock so there is no other process listening
@@ -101,7 +86,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
101
86
  */
102
87
  if (errno != EADDRINUSE
103
88
  || unlink(pipe_fname) == -1
104
- || bind(sockfd, (struct sockaddr*)&sun, sizeof sun) == -1) {
89
+ || bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr) == -1) {
105
90
  /* Convert ENOENT to EACCES for compatibility with Windows. */
106
91
  uv_err_new(handle->loop, (errno == ENOENT) ? EACCES : errno);
107
92
  goto out;
@@ -185,11 +170,16 @@ int uv_pipe_cleanup(uv_pipe_t* handle) {
185
170
  }
186
171
 
187
172
 
173
+ void uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
174
+ uv__stream_open((uv_stream_t*)handle, fd, UV_READABLE | UV_WRITABLE);
175
+ }
176
+
177
+
188
178
  int uv_pipe_connect(uv_connect_t* req,
189
179
  uv_pipe_t* handle,
190
180
  const char* name,
191
181
  uv_connect_cb cb) {
192
- struct sockaddr_un sun;
182
+ struct sockaddr_un saddr;
193
183
  int saved_errno;
194
184
  int sockfd;
195
185
  int status;
@@ -204,15 +194,15 @@ int uv_pipe_connect(uv_connect_t* req,
204
194
  goto out;
205
195
  }
206
196
 
207
- memset(&sun, 0, sizeof sun);
208
- uv__strlcpy(sun.sun_path, name, sizeof(sun.sun_path));
209
- sun.sun_family = AF_UNIX;
197
+ memset(&saddr, 0, sizeof saddr);
198
+ uv__strlcpy(saddr.sun_path, name, sizeof(saddr.sun_path));
199
+ saddr.sun_family = AF_UNIX;
210
200
 
211
201
  /* We don't check for EINPROGRESS. Think about it: the socket
212
202
  * is either there or not.
213
203
  */
214
204
  do {
215
- r = connect(sockfd, (struct sockaddr*)&sun, sizeof sun);
205
+ r = connect(sockfd, (struct sockaddr*)&saddr, sizeof saddr);
216
206
  }
217
207
  while (r == -1 && errno == EINTR);
218
208
 
@@ -251,7 +241,7 @@ out:
251
241
 
252
242
  /* TODO merge with uv__server_io()? */
253
243
  void uv__pipe_accept(EV_P_ ev_io* watcher, int revents) {
254
- struct sockaddr_un sun;
244
+ struct sockaddr_un saddr;
255
245
  uv_pipe_t* pipe;
256
246
  int saved_errno;
257
247
  int sockfd;
@@ -262,7 +252,7 @@ void uv__pipe_accept(EV_P_ ev_io* watcher, int revents) {
262
252
  assert(pipe->type == UV_NAMED_PIPE);
263
253
  assert(pipe->pipe_fname != NULL);
264
254
 
265
- sockfd = uv__accept(pipe->fd, (struct sockaddr *)&sun, sizeof sun);
255
+ sockfd = uv__accept(pipe->fd, (struct sockaddr *)&saddr, sizeof saddr);
266
256
  if (sockfd == -1) {
267
257
  if (errno == EAGAIN || errno == EWOULDBLOCK) {
268
258
  assert(0 && "EAGAIN on uv__accept(pipefd)");
@@ -26,6 +26,7 @@
26
26
  #include <assert.h>
27
27
  #include <errno.h>
28
28
  #include <sys/wait.h>
29
+ #include <fcntl.h> /* O_CLOEXEC, O_NONBLOCK */
29
30
  #include <poll.h>
30
31
  #include <unistd.h>
31
32
  #include <stdio.h>
@@ -178,16 +179,28 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
178
179
  if (stdin_pipe[0] >= 0) {
179
180
  uv__close(stdin_pipe[1]);
180
181
  dup2(stdin_pipe[0], STDIN_FILENO);
182
+ } else {
183
+ /* Reset flags that might be set by Node */
184
+ uv__cloexec(STDIN_FILENO, 0);
185
+ uv__nonblock(STDIN_FILENO, 0);
181
186
  }
182
187
 
183
188
  if (stdout_pipe[1] >= 0) {
184
189
  uv__close(stdout_pipe[0]);
185
190
  dup2(stdout_pipe[1], STDOUT_FILENO);
191
+ } else {
192
+ /* Reset flags that might be set by Node */
193
+ uv__cloexec(STDOUT_FILENO, 0);
194
+ uv__nonblock(STDOUT_FILENO, 0);
186
195
  }
187
196
 
188
197
  if (stderr_pipe[1] >= 0) {
189
198
  uv__close(stderr_pipe[0]);
190
199
  dup2(stderr_pipe[1], STDERR_FILENO);
200
+ } else {
201
+ /* Reset flags that might be set by Node */
202
+ uv__cloexec(STDERR_FILENO, 0);
203
+ uv__nonblock(STDERR_FILENO, 0);
191
204
  }
192
205
 
193
206
  if (options.cwd && chdir(options.cwd)) {
@@ -26,11 +26,12 @@
26
26
  #include <errno.h>
27
27
  #include <unistd.h>
28
28
  #include <stdlib.h>
29
+ #include <string.h>
29
30
  #include <sys/uio.h>
30
31
 
31
32
 
32
33
  static void uv__stream_connect(uv_stream_t*);
33
- static uv_write_t* uv__write(uv_stream_t* stream);
34
+ static void uv__write(uv_stream_t* stream);
34
35
  static void uv__read(uv_stream_t* stream);
35
36
 
36
37
 
@@ -46,6 +47,34 @@ static size_t uv__buf_count(uv_buf_t bufs[], int bufcnt) {
46
47
  }
47
48
 
48
49
 
50
+ void uv__stream_init(uv_loop_t* loop,
51
+ uv_stream_t* stream,
52
+ uv_handle_type type) {
53
+ uv__handle_init(loop, (uv_handle_t*)stream, type);
54
+
55
+ stream->alloc_cb = NULL;
56
+ stream->close_cb = NULL;
57
+ stream->connection_cb = NULL;
58
+ stream->connect_req = NULL;
59
+ stream->accepted_fd = -1;
60
+ stream->fd = -1;
61
+ stream->delayed_error = 0;
62
+ ngx_queue_init(&stream->write_queue);
63
+ ngx_queue_init(&stream->write_completed_queue);
64
+ stream->write_queue_size = 0;
65
+
66
+ ev_init(&stream->read_watcher, uv__stream_io);
67
+ stream->read_watcher.data = stream;
68
+
69
+ ev_init(&stream->write_watcher, uv__stream_io);
70
+ stream->write_watcher.data = stream;
71
+
72
+ assert(ngx_queue_empty(&stream->write_queue));
73
+ assert(ngx_queue_empty(&stream->write_completed_queue));
74
+ assert(stream->write_queue_size == 0);
75
+ }
76
+
77
+
49
78
  int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
50
79
  socklen_t yes;
51
80
 
@@ -74,6 +103,39 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
74
103
  }
75
104
 
76
105
 
106
+ void uv__stream_destroy(uv_stream_t* stream) {
107
+ uv_write_t* req;
108
+ ngx_queue_t* q;
109
+
110
+ assert(stream->flags & UV_CLOSED);
111
+
112
+ while (!ngx_queue_empty(&stream->write_queue)) {
113
+ q = ngx_queue_head(&stream->write_queue);
114
+ ngx_queue_remove(q);
115
+
116
+ req = ngx_queue_data(q, uv_write_t, queue);
117
+ if (req->bufs != req->bufsml)
118
+ free(req->bufs);
119
+
120
+ if (req->cb) {
121
+ uv_err_new_artificial(req->handle->loop, UV_EINTR);
122
+ req->cb(req, -1);
123
+ }
124
+ }
125
+
126
+ while (!ngx_queue_empty(&stream->write_completed_queue)) {
127
+ q = ngx_queue_head(&stream->write_completed_queue);
128
+ ngx_queue_remove(q);
129
+
130
+ req = ngx_queue_data(q, uv_write_t, queue);
131
+ if (req->cb) {
132
+ uv_err_new_artificial(req->handle->loop, UV_OK);
133
+ req->cb(req, 0);
134
+ }
135
+ }
136
+ }
137
+
138
+
77
139
  void uv__server_io(EV_P_ ev_io* watcher, int revents) {
78
140
  int fd;
79
141
  struct sockaddr_storage addr;
@@ -225,10 +287,28 @@ static void uv__drain(uv_stream_t* stream) {
225
287
  }
226
288
 
227
289
 
290
+ static void uv__write_req_finish(uv_write_t* req) {
291
+ uv_stream_t* stream = req->handle;
292
+
293
+ /* Pop the req off tcp->write_queue. */
294
+ ngx_queue_remove(&req->queue);
295
+ if (req->bufs != req->bufsml) {
296
+ free(req->bufs);
297
+ }
298
+ req->bufs = NULL;
299
+
300
+ /* Add it to the write_completed_queue where it will have its
301
+ * callback called in the near future.
302
+ */
303
+ ngx_queue_insert_tail(&stream->write_completed_queue, &req->queue);
304
+ ev_feed_event(stream->loop->ev, &stream->write_watcher, EV_WRITE);
305
+ }
306
+
307
+
228
308
  /* On success returns NULL. On error returns a pointer to the write request
229
309
  * which had the error.
230
310
  */
231
- static uv_write_t* uv__write(uv_stream_t* stream) {
311
+ static void uv__write(uv_stream_t* stream) {
232
312
  uv_write_t* req;
233
313
  struct iovec* iov;
234
314
  int iovcnt;
@@ -242,7 +322,7 @@ static uv_write_t* uv__write(uv_stream_t* stream) {
242
322
  req = uv_write_queue_head(stream);
243
323
  if (!req) {
244
324
  assert(stream->write_queue_size == 0);
245
- return NULL;
325
+ return;
246
326
  }
247
327
 
248
328
  assert(req->handle == stream);
@@ -270,8 +350,9 @@ static uv_write_t* uv__write(uv_stream_t* stream) {
270
350
  if (n < 0) {
271
351
  if (errno != EAGAIN) {
272
352
  /* Error */
273
- uv_err_new(stream->loop, errno);
274
- return req;
353
+ req->error = errno;
354
+ uv__write_req_finish(req);
355
+ return;
275
356
  }
276
357
  } else {
277
358
  /* Successful write */
@@ -305,21 +386,9 @@ static uv_write_t* uv__write(uv_stream_t* stream) {
305
386
  if (req->write_index == req->bufcnt) {
306
387
  /* Then we're done! */
307
388
  assert(n == 0);
308
-
309
- /* Pop the req off tcp->write_queue. */
310
- ngx_queue_remove(&req->queue);
311
- if (req->bufs != req->bufsml) {
312
- free(req->bufs);
313
- }
314
- req->bufs = NULL;
315
-
316
- /* Add it to the write_completed_queue where it will have its
317
- * callback called in the near future.
318
- * TODO: start trying to write the next request.
319
- */
320
- ngx_queue_insert_tail(&stream->write_completed_queue, &req->queue);
321
- ev_feed_event(stream->loop->ev, &stream->write_watcher, EV_WRITE);
322
- return NULL;
389
+ uv__write_req_finish(req);
390
+ /* TODO: start trying to write the next request. */
391
+ return;
323
392
  }
324
393
  }
325
394
  }
@@ -330,8 +399,6 @@ static uv_write_t* uv__write(uv_stream_t* stream) {
330
399
 
331
400
  /* We're not done. */
332
401
  ev_io_start(stream->loop->ev, &stream->write_watcher);
333
-
334
- return NULL;
335
402
  }
336
403
 
337
404
 
@@ -349,7 +416,8 @@ static void uv__write_callbacks(uv_stream_t* stream) {
349
416
 
350
417
  /* NOTE: call callback AFTER freeing the request data. */
351
418
  if (req->cb) {
352
- req->cb(req, 0);
419
+ uv_err_new_artificial(stream->loop, req->error);
420
+ req->cb(req, req->error ? -1 : 0);
353
421
  }
354
422
 
355
423
  callbacks_made++;
@@ -466,15 +534,8 @@ void uv__stream_io(EV_P_ ev_io* watcher, int revents) {
466
534
  }
467
535
 
468
536
  if (revents & EV_WRITE) {
469
- uv_write_t* req = uv__write(stream);
470
- if (req) {
471
- /* Error. Notify the user. */
472
- if (req->cb) {
473
- req->cb(req, -1);
474
- }
475
- } else {
476
- uv__write_callbacks(stream);
477
- }
537
+ uv__write(stream);
538
+ uv__write_callbacks(stream);
478
539
  }
479
540
  }
480
541
  }
@@ -602,34 +663,29 @@ int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr,
602
663
  /* The buffers to be written must remain valid until the callback is called.
603
664
  * This is not required for the uv_buf_t array.
604
665
  */
605
- int uv_write(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt,
666
+ int uv_write(uv_write_t* req, uv_stream_t* stream, uv_buf_t bufs[], int bufcnt,
606
667
  uv_write_cb cb) {
607
- uv_stream_t* stream;
608
668
  int empty_queue;
609
669
 
610
- stream = (uv_stream_t*)handle;
611
-
612
- /* Initialize the req */
613
- uv__req_init((uv_req_t*) req);
614
- req->cb = cb;
615
- req->handle = handle;
616
- ngx_queue_init(&req->queue);
617
-
618
- assert((handle->type == UV_TCP || handle->type == UV_NAMED_PIPE)
670
+ assert((stream->type == UV_TCP || stream->type == UV_NAMED_PIPE)
619
671
  && "uv_write (unix) does not yet support other types of streams");
620
672
 
621
- empty_queue = (stream->write_queue_size == 0);
622
-
623
673
  if (stream->fd < 0) {
624
674
  uv_err_new(stream->loop, EBADF);
625
675
  return -1;
626
676
  }
627
677
 
628
- ngx_queue_init(&req->queue);
629
- req->type = UV_WRITE;
678
+ empty_queue = (stream->write_queue_size == 0);
630
679
 
680
+ /* Initialize the req */
681
+ uv__req_init((uv_req_t*) req);
682
+ req->cb = cb;
683
+ req->handle = stream;
684
+ req->error = 0;
685
+ req->type = UV_WRITE;
686
+ ngx_queue_init(&req->queue);
631
687
 
632
- if (bufcnt < UV_REQ_BUFSML_SIZE) {
688
+ if (bufcnt <= UV_REQ_BUFSML_SIZE) {
633
689
  req->bufs = req->bufsml;
634
690
  }
635
691
  else {
@@ -659,22 +715,8 @@ int uv_write(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt,
659
715
  * for the fd to become writable.
660
716
  */
661
717
  if (empty_queue) {
662
- if (uv__write(stream)) {
663
- /* Error. uv_last_error has been set. */
664
- return -1;
665
- }
666
- }
667
-
668
- /* If the queue is now empty - we've flushed the request already. That
669
- * means we need to make the callback. The callback can only be done on a
670
- * fresh stack so we feed the event loop in order to service it.
671
- */
672
- if (ngx_queue_empty(&stream->write_queue)) {
673
- ev_feed_event(stream->loop->ev, &stream->write_watcher, EV_WRITE);
718
+ uv__write(stream);
674
719
  } else {
675
- /* Otherwise there is data to write - so we should wait for the file
676
- * descriptor to become writable.
677
- */
678
720
  ev_io_start(stream->loop->ev, &stream->write_watcher);
679
721
  }
680
722