PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/ext/kgio/read_write.c

https://github.com/wsylvest/kgio
C | 396 lines | 239 code | 42 blank | 115 comment | 44 complexity | 93dd970c43a9a016e38ebb65ed600cfd MD5 | raw file
  1. #include "kgio.h"
  2. static VALUE mKgio_WaitReadable, mKgio_WaitWritable;
  3. static VALUE eErrno_EPIPE, eErrno_ECONNRESET;
  4. /*
  5. * we know MSG_DONTWAIT works properly on all stream sockets under Linux
  6. * we can define this macro for other platforms as people care and
  7. * notice.
  8. */
  9. #if defined(__linux__) && ! defined(USE_MSG_DONTWAIT)
  10. # define USE_MSG_DONTWAIT
  11. #endif
  12. NORETURN(static void raise_empty_bt(VALUE, const char *));
  13. NORETURN(static void my_eof_error(void));
  14. NORETURN(static void wr_sys_fail(const char *));
  15. static void raise_empty_bt(VALUE err, const char *msg)
  16. {
  17. VALUE exc = rb_exc_new2(err, msg);
  18. VALUE bt = rb_ary_new();
  19. rb_funcall(exc, rb_intern("set_backtrace"), 1, bt);
  20. rb_exc_raise(exc);
  21. }
  22. static void my_eof_error(void)
  23. {
  24. raise_empty_bt(rb_eEOFError, "");
  25. }
  26. static void wr_sys_fail(const char *msg)
  27. {
  28. switch (errno) {
  29. case EPIPE:
  30. errno = 0;
  31. raise_empty_bt(eErrno_EPIPE, msg);
  32. case ECONNRESET:
  33. errno = 0;
  34. raise_empty_bt(eErrno_ECONNRESET, msg);
  35. }
  36. rb_sys_fail(msg);
  37. }
  38. static void prepare_read(struct io_args *a, int argc, VALUE *argv, VALUE io)
  39. {
  40. VALUE length;
  41. a->io = io;
  42. a->fd = my_fileno(io);
  43. rb_scan_args(argc, argv, "11", &length, &a->buf);
  44. a->len = NUM2LONG(length);
  45. if (NIL_P(a->buf)) {
  46. a->buf = rb_str_new(NULL, a->len);
  47. } else {
  48. StringValue(a->buf);
  49. rb_str_resize(a->buf, a->len);
  50. }
  51. a->ptr = RSTRING_PTR(a->buf);
  52. }
  53. static int read_check(struct io_args *a, long n, const char *msg, int io_wait)
  54. {
  55. if (n == -1) {
  56. if (errno == EINTR)
  57. return -1;
  58. rb_str_set_len(a->buf, 0);
  59. if (errno == EAGAIN) {
  60. if (io_wait) {
  61. kgio_wait_readable(a->io, a->fd);
  62. /* buf may be modified in other thread/fiber */
  63. rb_str_resize(a->buf, a->len);
  64. a->ptr = RSTRING_PTR(a->buf);
  65. return -1;
  66. } else {
  67. a->buf = mKgio_WaitReadable;
  68. return 0;
  69. }
  70. }
  71. rb_sys_fail(msg);
  72. }
  73. rb_str_set_len(a->buf, n);
  74. if (n == 0)
  75. a->buf = Qnil;
  76. return 0;
  77. }
  78. static VALUE my_read(int io_wait, int argc, VALUE *argv, VALUE io)
  79. {
  80. struct io_args a;
  81. long n;
  82. prepare_read(&a, argc, argv, io);
  83. if (a.len > 0) {
  84. set_nonblocking(a.fd);
  85. retry:
  86. n = (long)read(a.fd, a.ptr, a.len);
  87. if (read_check(&a, n, "read", io_wait) != 0)
  88. goto retry;
  89. }
  90. return a.buf;
  91. }
  92. /*
  93. * call-seq:
  94. *
  95. * io.kgio_read(maxlen) -> buffer
  96. * io.kgio_read(maxlen, buffer) -> buffer
  97. *
  98. * Reads at most maxlen bytes from the stream socket. Returns with a
  99. * newly allocated buffer, or may reuse an existing buffer if supplied.
  100. *
  101. * Calls the method assigned to Kgio.wait_readable, or blocks in a
  102. * thread-safe manner for writability.
  103. *
  104. * Returns nil on EOF.
  105. *
  106. * This behaves like read(2) and IO#readpartial, NOT fread(3) or
  107. * IO#read which possess read-in-full behavior.
  108. */
  109. static VALUE kgio_read(int argc, VALUE *argv, VALUE io)
  110. {
  111. return my_read(1, argc, argv, io);
  112. }
  113. /*
  114. * Same as Kgio::PipeMethods#kgio_read, except EOFError is raised
  115. * on EOF without a backtrace. This method is intended as a
  116. * drop-in replacement for places where IO#readpartial is used, and
  117. * may be aliased as such.
  118. */
  119. static VALUE kgio_read_bang(int argc, VALUE *argv, VALUE io)
  120. {
  121. VALUE rv = my_read(1, argc, argv, io);
  122. if (NIL_P(rv)) my_eof_error();
  123. return rv;
  124. }
  125. /*
  126. * call-seq:
  127. *
  128. * io.kgio_tryread(maxlen) -> buffer
  129. * io.kgio_tryread(maxlen, buffer) -> buffer
  130. *
  131. * Reads at most maxlen bytes from the stream socket. Returns with a
  132. * newly allocated buffer, or may reuse an existing buffer if supplied.
  133. *
  134. * Returns nil on EOF.
  135. *
  136. * Returns Kgio::WaitReadable if EAGAIN is encountered.
  137. */
  138. static VALUE kgio_tryread(int argc, VALUE *argv, VALUE io)
  139. {
  140. return my_read(0, argc, argv, io);
  141. }
  142. #ifdef USE_MSG_DONTWAIT
  143. static VALUE my_recv(int io_wait, int argc, VALUE *argv, VALUE io)
  144. {
  145. struct io_args a;
  146. long n;
  147. prepare_read(&a, argc, argv, io);
  148. if (a.len > 0) {
  149. retry:
  150. n = (long)recv(a.fd, a.ptr, a.len, MSG_DONTWAIT);
  151. if (read_check(&a, n, "recv", io_wait) != 0)
  152. goto retry;
  153. }
  154. return a.buf;
  155. }
  156. /*
  157. * This method may be optimized on some systems (e.g. GNU/Linux) to use
  158. * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
  159. * Otherwise this is the same as Kgio::PipeMethods#kgio_read
  160. */
  161. static VALUE kgio_recv(int argc, VALUE *argv, VALUE io)
  162. {
  163. return my_recv(1, argc, argv, io);
  164. }
  165. /*
  166. * Same as Kgio::SocketMethods#kgio_read, except EOFError is raised
  167. * on EOF without a backtrace
  168. */
  169. static VALUE kgio_recv_bang(int argc, VALUE *argv, VALUE io)
  170. {
  171. VALUE rv = my_recv(1, argc, argv, io);
  172. if (NIL_P(rv)) my_eof_error();
  173. return rv;
  174. }
  175. /*
  176. * This method may be optimized on some systems (e.g. GNU/Linux) to use
  177. * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
  178. * Otherwise this is the same as Kgio::PipeMethods#kgio_tryread
  179. */
  180. static VALUE kgio_tryrecv(int argc, VALUE *argv, VALUE io)
  181. {
  182. return my_recv(0, argc, argv, io);
  183. }
  184. #else /* ! USE_MSG_DONTWAIT */
  185. # define kgio_recv kgio_read
  186. # define kgio_recv_bang kgio_read_bang
  187. # define kgio_tryrecv kgio_tryread
  188. #endif /* USE_MSG_DONTWAIT */
  189. static void prepare_write(struct io_args *a, VALUE io, VALUE str)
  190. {
  191. a->buf = (TYPE(str) == T_STRING) ? str : rb_obj_as_string(str);
  192. a->ptr = RSTRING_PTR(a->buf);
  193. a->len = RSTRING_LEN(a->buf);
  194. a->io = io;
  195. a->fd = my_fileno(io);
  196. }
  197. static int write_check(struct io_args *a, long n, const char *msg, int io_wait)
  198. {
  199. if (a->len == n) {
  200. done:
  201. a->buf = Qnil;
  202. } else if (n == -1) {
  203. if (errno == EINTR)
  204. return -1;
  205. if (errno == EAGAIN) {
  206. long written = RSTRING_LEN(a->buf) - a->len;
  207. if (io_wait) {
  208. kgio_wait_writable(a->io, a->fd);
  209. /* buf may be modified in other thread/fiber */
  210. a->len = RSTRING_LEN(a->buf) - written;
  211. if (a->len <= 0)
  212. goto done;
  213. a->ptr = RSTRING_PTR(a->buf) + written;
  214. return -1;
  215. } else if (written > 0) {
  216. a->buf = rb_str_new(a->ptr, a->len);
  217. } else {
  218. a->buf = mKgio_WaitWritable;
  219. }
  220. return 0;
  221. }
  222. wr_sys_fail(msg);
  223. } else {
  224. assert(n >= 0 && n < a->len && "write/send syscall broken?");
  225. a->ptr += n;
  226. a->len -= n;
  227. return -1;
  228. }
  229. return 0;
  230. }
  231. static VALUE my_write(VALUE io, VALUE str, int io_wait)
  232. {
  233. struct io_args a;
  234. long n;
  235. prepare_write(&a, io, str);
  236. set_nonblocking(a.fd);
  237. retry:
  238. n = (long)write(a.fd, a.ptr, a.len);
  239. if (write_check(&a, n, "write", io_wait) != 0)
  240. goto retry;
  241. return a.buf;
  242. }
  243. /*
  244. * call-seq:
  245. *
  246. * io.kgio_write(str) -> nil
  247. *
  248. * Returns nil when the write completes.
  249. *
  250. * Calls the method Kgio.wait_writable if it is set. Otherwise this
  251. * blocks in a thread-safe manner until all data is written or a
  252. * fatal error occurs.
  253. */
  254. static VALUE kgio_write(VALUE io, VALUE str)
  255. {
  256. return my_write(io, str, 1);
  257. }
  258. /*
  259. * call-seq:
  260. *
  261. * io.kgio_trywrite(str) -> nil or Kgio::WaitWritable
  262. *
  263. * Returns nil if the write was completed in full.
  264. *
  265. * Returns a String containing the unwritten portion if EAGAIN
  266. * was encountered, but some portion was successfully written.
  267. *
  268. * Returns Kgio::WaitWritable if EAGAIN is encountered and nothing
  269. * was written.
  270. */
  271. static VALUE kgio_trywrite(VALUE io, VALUE str)
  272. {
  273. return my_write(io, str, 0);
  274. }
  275. #ifdef USE_MSG_DONTWAIT
  276. /*
  277. * This method behaves like Kgio::PipeMethods#kgio_write, except
  278. * it will use send(2) with the MSG_DONTWAIT flag on sockets to
  279. * avoid unnecessary calls to fcntl(2).
  280. */
  281. static VALUE my_send(VALUE io, VALUE str, int io_wait)
  282. {
  283. struct io_args a;
  284. long n;
  285. prepare_write(&a, io, str);
  286. retry:
  287. n = (long)send(a.fd, a.ptr, a.len, MSG_DONTWAIT);
  288. if (write_check(&a, n, "send", io_wait) != 0)
  289. goto retry;
  290. return a.buf;
  291. }
  292. /*
  293. * This method may be optimized on some systems (e.g. GNU/Linux) to use
  294. * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
  295. * Otherwise this is the same as Kgio::PipeMethods#kgio_write
  296. */
  297. static VALUE kgio_send(VALUE io, VALUE str)
  298. {
  299. return my_send(io, str, 1);
  300. }
  301. /*
  302. * This method may be optimized on some systems (e.g. GNU/Linux) to use
  303. * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
  304. * Otherwise this is the same as Kgio::PipeMethods#kgio_trywrite
  305. */
  306. static VALUE kgio_trysend(VALUE io, VALUE str)
  307. {
  308. return my_send(io, str, 0);
  309. }
  310. #else /* ! USE_MSG_DONTWAIT */
  311. # define kgio_send kgio_write
  312. # define kgio_trysend kgio_trywrite
  313. #endif /* ! USE_MSG_DONTWAIT */
  314. void init_kgio_read_write(void)
  315. {
  316. VALUE mPipeMethods, mSocketMethods;
  317. VALUE mKgio = rb_define_module("Kgio");
  318. mKgio_WaitReadable = rb_const_get(mKgio, rb_intern("WaitReadable"));
  319. mKgio_WaitWritable = rb_const_get(mKgio, rb_intern("WaitWritable"));
  320. /*
  321. * Document-module: Kgio::PipeMethods
  322. *
  323. * This module may be used used to create classes that respond to
  324. * various Kgio methods for reading and writing. This is included
  325. * in Kgio::Pipe by default.
  326. */
  327. mPipeMethods = rb_define_module_under(mKgio, "PipeMethods");
  328. rb_define_method(mPipeMethods, "kgio_read", kgio_read, -1);
  329. rb_define_method(mPipeMethods, "kgio_read!", kgio_read_bang, -1);
  330. rb_define_method(mPipeMethods, "kgio_write", kgio_write, 1);
  331. rb_define_method(mPipeMethods, "kgio_tryread", kgio_tryread, -1);
  332. rb_define_method(mPipeMethods, "kgio_trywrite", kgio_trywrite, 1);
  333. /*
  334. * Document-module: Kgio::SocketMethods
  335. *
  336. * This method behaves like Kgio::PipeMethods, but contains
  337. * optimizations for sockets on certain operating systems
  338. * (e.g. GNU/Linux).
  339. */
  340. mSocketMethods = rb_define_module_under(mKgio, "SocketMethods");
  341. rb_define_method(mSocketMethods, "kgio_read", kgio_recv, -1);
  342. rb_define_method(mSocketMethods, "kgio_read!", kgio_recv_bang, -1);
  343. rb_define_method(mSocketMethods, "kgio_write", kgio_send, 1);
  344. rb_define_method(mSocketMethods, "kgio_tryread", kgio_tryrecv, -1);
  345. rb_define_method(mSocketMethods, "kgio_trywrite", kgio_trysend, 1);
  346. /*
  347. * Returns the client IPv4 address of the socket in dotted quad
  348. * form as a string. This is always the value of the
  349. * Kgio::LOCALHOST constant for UNIX domain sockets.
  350. */
  351. rb_define_attr(mSocketMethods, "kgio_addr", 1, 1);
  352. eErrno_EPIPE = rb_const_get(rb_mErrno, rb_intern("EPIPE"));
  353. eErrno_ECONNRESET = rb_const_get(rb_mErrno, rb_intern("ECONNRESET"));
  354. }