Ruby  2.5.0dev(2017-10-22revision60238)
unixsocket.c
Go to the documentation of this file.
1 /************************************************
2 
3  unixsocket.c -
4 
5  created at: Thu Mar 31 12:21:29 JST 1994
6 
7  Copyright (C) 1993-2007 Yukihiro Matsumoto
8 
9 ************************************************/
10 
11 #include "rubysocket.h"
12 
13 #ifdef HAVE_SYS_UN_H
14 struct unixsock_arg {
15  struct sockaddr_un *sockaddr;
16  socklen_t sockaddrlen;
17  int fd;
18 };
19 
20 static VALUE
21 unixsock_connect_internal(VALUE a)
22 {
23  struct unixsock_arg *arg = (struct unixsock_arg *)a;
24  return (VALUE)rsock_connect(arg->fd, (struct sockaddr*)arg->sockaddr,
25  arg->sockaddrlen, 0);
26 }
27 
28 VALUE
29 rsock_init_unixsock(VALUE sock, VALUE path, int server)
30 {
31  struct sockaddr_un sockaddr;
32  socklen_t sockaddrlen;
33  int fd, status;
34  rb_io_t *fptr;
35 
36  SafeStringValue(path);
37 
38  INIT_SOCKADDR_UN(&sockaddr, sizeof(struct sockaddr_un));
39  if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
40  rb_raise(rb_eArgError, "too long unix socket path (%ldbytes given but %dbytes max)",
41  RSTRING_LEN(path), (int)sizeof(sockaddr.sun_path));
42  }
43  memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
44  sockaddrlen = rsock_unix_sockaddr_len(path);
45 
46  fd = rsock_socket(AF_UNIX, SOCK_STREAM, 0);
47  if (fd < 0) {
48  rsock_sys_fail_path("socket(2)", path);
49  }
50 
51  if (server) {
52  status = bind(fd, (struct sockaddr*)&sockaddr, sockaddrlen);
53  }
54  else {
55  int prot;
56  struct unixsock_arg arg;
57  arg.sockaddr = &sockaddr;
58  arg.sockaddrlen = sockaddrlen;
59  arg.fd = fd;
60  status = (int)rb_protect(unixsock_connect_internal, (VALUE)&arg, &prot);
61  if (prot) {
62  close(fd);
63  rb_jump_tag(prot);
64  }
65  }
66 
67  if (status < 0) {
68  int e = errno;
69  close(fd);
70  rsock_syserr_fail_path(e, "connect(2)", path);
71  }
72 
73  if (server) {
74  if (listen(fd, SOMAXCONN) < 0) {
75  int e = errno;
76  close(fd);
77  rsock_syserr_fail_path(e, "listen(2)", path);
78  }
79  }
80 
81  rsock_init_sock(sock, fd);
82  if (server) {
83  GetOpenFile(sock, fptr);
84  fptr->pathv = rb_str_new_frozen(path);
85  }
86 
87  return sock;
88 }
89 
90 /*
91  * call-seq:
92  * UNIXSocket.new(path) => unixsocket
93  *
94  * Creates a new UNIX client socket connected to _path_.
95  *
96  * require 'socket'
97  *
98  * s = UNIXSocket.new("/tmp/sock")
99  * s.send "hello", 0
100  *
101  */
102 static VALUE
103 unix_init(VALUE sock, VALUE path)
104 {
105  return rsock_init_unixsock(sock, path, 0);
106 }
107 
108 /*
109  * call-seq:
110  * unixsocket.path => path
111  *
112  * Returns the path of the local address of unixsocket.
113  *
114  * s = UNIXServer.new("/tmp/sock")
115  * p s.path #=> "/tmp/sock"
116  *
117  */
118 static VALUE
119 unix_path(VALUE sock)
120 {
121  rb_io_t *fptr;
122 
123  GetOpenFile(sock, fptr);
124  if (NIL_P(fptr->pathv)) {
125  struct sockaddr_un addr;
126  socklen_t len = (socklen_t)sizeof(addr);
127  socklen_t len0 = len;
128  if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
129  rsock_sys_fail_path("getsockname(2)", fptr->pathv);
130  if (len0 < len) len = len0;
131  fptr->pathv = rb_obj_freeze(rsock_unixpath_str(&addr, len));
132  }
133  return rb_str_dup(fptr->pathv);
134 }
135 
136 /*
137  * call-seq:
138  * unixsocket.recvfrom(maxlen [, flags[, outbuf]]) => [mesg, unixaddress]
139  *
140  * Receives a message via _unixsocket_.
141  *
142  * _maxlen_ is the maximum number of bytes to receive.
143  *
144  * _flags_ should be a bitwise OR of Socket::MSG_* constants.
145  *
146  * _outbuf_ will contain only the received data after the method call
147  * even if it is not empty at the beginning.
148  *
149  * s1 = Socket.new(:UNIX, :DGRAM, 0)
150  * s1_ai = Addrinfo.unix("/tmp/sock1")
151  * s1.bind(s1_ai)
152  *
153  * s2 = Socket.new(:UNIX, :DGRAM, 0)
154  * s2_ai = Addrinfo.unix("/tmp/sock2")
155  * s2.bind(s2_ai)
156  * s3 = UNIXSocket.for_fd(s2.fileno)
157  *
158  * s1.send "a", 0, s2_ai
159  * p s3.recvfrom(10) #=> ["a", ["AF_UNIX", "/tmp/sock1"]]
160  *
161  */
162 static VALUE
163 unix_recvfrom(int argc, VALUE *argv, VALUE sock)
164 {
165  return rsock_s_recvfrom(sock, argc, argv, RECV_UNIX);
166 }
167 
168 #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && defined(SCM_RIGHTS)
169 #define FD_PASSING_BY_MSG_CONTROL 1
170 #else
171 #define FD_PASSING_BY_MSG_CONTROL 0
172 #endif
173 
174 #if defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS)
175 #define FD_PASSING_BY_MSG_ACCRIGHTS 1
176 #else
177 #define FD_PASSING_BY_MSG_ACCRIGHTS 0
178 #endif
179 
180 struct iomsg_arg {
181  int fd;
182  struct msghdr msg;
183 };
184 
185 #if defined(HAVE_SENDMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
186 static VALUE
187 sendmsg_blocking(void *data)
188 {
189  struct iomsg_arg *arg = data;
190  return sendmsg(arg->fd, &arg->msg, 0);
191 }
192 
193 /*
194  * call-seq:
195  * unixsocket.send_io(io) => nil
196  *
197  * Sends _io_ as file descriptor passing.
198  *
199  * s1, s2 = UNIXSocket.pair
200  *
201  * s1.send_io STDOUT
202  * stdout = s2.recv_io
203  *
204  * p STDOUT.fileno #=> 1
205  * p stdout.fileno #=> 6
206  *
207  * stdout.puts "hello" # outputs "hello\n" to standard output.
208  *
209  * _io_ may be any kind of IO object or integer file descriptor.
210  */
211 static VALUE
212 unix_send_io(VALUE sock, VALUE val)
213 {
214  int fd;
215  rb_io_t *fptr;
216  struct iomsg_arg arg;
217  struct iovec vec[1];
218  char buf[1];
219 
220 #if FD_PASSING_BY_MSG_CONTROL
221  union {
222  struct cmsghdr hdr;
223  char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8];
224  } cmsg;
225 #endif
226 
227  if (rb_obj_is_kind_of(val, rb_cIO)) {
228  rb_io_t *valfptr;
229  GetOpenFile(val, valfptr);
230  fd = valfptr->fd;
231  }
232  else if (FIXNUM_P(val)) {
233  fd = FIX2INT(val);
234  }
235  else {
236  rb_raise(rb_eTypeError, "neither IO nor file descriptor");
237  }
238 
239  GetOpenFile(sock, fptr);
240 
241  arg.msg.msg_name = NULL;
242  arg.msg.msg_namelen = 0;
243 
244  /* Linux and Solaris doesn't work if msg_iov is NULL. */
245  buf[0] = '\0';
246  vec[0].iov_base = buf;
247  vec[0].iov_len = 1;
248  arg.msg.msg_iov = vec;
249  arg.msg.msg_iovlen = 1;
250 
251 #if FD_PASSING_BY_MSG_CONTROL
252  arg.msg.msg_control = (caddr_t)&cmsg;
253  arg.msg.msg_controllen = (socklen_t)CMSG_LEN(sizeof(int));
254  arg.msg.msg_flags = 0;
255  MEMZERO((char*)&cmsg, char, sizeof(cmsg));
256  cmsg.hdr.cmsg_len = (socklen_t)CMSG_LEN(sizeof(int));
257  cmsg.hdr.cmsg_level = SOL_SOCKET;
258  cmsg.hdr.cmsg_type = SCM_RIGHTS;
259  memcpy(CMSG_DATA(&cmsg.hdr), &fd, sizeof(int));
260 #else
261  arg.msg.msg_accrights = (caddr_t)&fd;
262  arg.msg.msg_accrightslen = sizeof(fd);
263 #endif
264 
265  arg.fd = fptr->fd;
266  while ((int)BLOCKING_REGION_FD(sendmsg_blocking, &arg) == -1) {
267  if (!rb_io_wait_writable(arg.fd))
268  rsock_sys_fail_path("sendmsg(2)", fptr->pathv);
269  }
270 
271  return Qnil;
272 }
273 #else
274 #define unix_send_io rb_f_notimplement
275 #endif
276 
277 #if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
278 static VALUE
279 recvmsg_blocking(void *data)
280 {
281  struct iomsg_arg *arg = data;
282  int flags = 0;
283  return rsock_recvmsg(arg->fd, &arg->msg, flags);
284 }
285 
286 /*
287  * call-seq:
288  * unixsocket.recv_io([klass [, mode]]) => io
289  *
290  * Example
291  *
292  * UNIXServer.open("/tmp/sock") {|serv|
293  * UNIXSocket.open("/tmp/sock") {|c|
294  * s = serv.accept
295  *
296  * c.send_io STDOUT
297  * stdout = s.recv_io
298  *
299  * p STDOUT.fileno #=> 1
300  * p stdout.fileno #=> 7
301  *
302  * stdout.puts "hello" # outputs "hello\n" to standard output.
303  * }
304  * }
305  *
306  * _klass_ will determine the class of _io_ returned (using the
307  * IO.for_fd singleton method or similar).
308  * If _klass_ is +nil+, an integer file descriptor is returned.
309  *
310  * _mode_ is the same as the argument passed to IO.for_fd
311  */
312 static VALUE
313 unix_recv_io(int argc, VALUE *argv, VALUE sock)
314 {
315  VALUE klass, mode;
316  rb_io_t *fptr;
317  struct iomsg_arg arg;
318  struct iovec vec[2];
319  char buf[1];
320 
321  int fd;
322 #if FD_PASSING_BY_MSG_CONTROL
323  union {
324  struct cmsghdr hdr;
325  char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8];
326  } cmsg;
327 #endif
328 
329  rb_scan_args(argc, argv, "02", &klass, &mode);
330  if (argc == 0)
331  klass = rb_cIO;
332  if (argc <= 1)
333  mode = Qnil;
334 
335  GetOpenFile(sock, fptr);
336 
337  arg.msg.msg_name = NULL;
338  arg.msg.msg_namelen = 0;
339 
340  vec[0].iov_base = buf;
341  vec[0].iov_len = sizeof(buf);
342  arg.msg.msg_iov = vec;
343  arg.msg.msg_iovlen = 1;
344 
345 #if FD_PASSING_BY_MSG_CONTROL
346  arg.msg.msg_control = (caddr_t)&cmsg;
347  arg.msg.msg_controllen = (socklen_t)CMSG_SPACE(sizeof(int));
348  arg.msg.msg_flags = 0;
349  cmsg.hdr.cmsg_len = (socklen_t)CMSG_LEN(sizeof(int));
350  cmsg.hdr.cmsg_level = SOL_SOCKET;
351  cmsg.hdr.cmsg_type = SCM_RIGHTS;
352  fd = -1;
353  memcpy(CMSG_DATA(&cmsg.hdr), &fd, sizeof(int));
354 #else
355  arg.msg.msg_accrights = (caddr_t)&fd;
356  arg.msg.msg_accrightslen = sizeof(fd);
357  fd = -1;
358 #endif
359 
360  arg.fd = fptr->fd;
361  while ((int)BLOCKING_REGION_FD(recvmsg_blocking, &arg) == -1) {
362  if (!rb_io_wait_readable(arg.fd))
363  rsock_sys_fail_path("recvmsg(2)", fptr->pathv);
364  }
365 
366 #if FD_PASSING_BY_MSG_CONTROL
367  if (arg.msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr)) {
369  "file descriptor was not passed (msg_controllen=%d smaller than sizeof(struct cmsghdr)=%d)",
370  (int)arg.msg.msg_controllen, (int)sizeof(struct cmsghdr));
371  }
372  if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
374  "file descriptor was not passed (cmsg_level=%d, %d expected)",
375  cmsg.hdr.cmsg_level, SOL_SOCKET);
376  }
377  if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
379  "file descriptor was not passed (cmsg_type=%d, %d expected)",
380  cmsg.hdr.cmsg_type, SCM_RIGHTS);
381  }
382  if (arg.msg.msg_controllen < (socklen_t)CMSG_LEN(sizeof(int))) {
384  "file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)",
385  (int)arg.msg.msg_controllen, (int)CMSG_LEN(sizeof(int)));
386  }
387  if ((socklen_t)CMSG_SPACE(sizeof(int)) < arg.msg.msg_controllen) {
389  "file descriptor was not passed (msg_controllen=%d bigger than CMSG_SPACE(sizeof(int))=%d)",
390  (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int)));
391  }
392  if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
393  rsock_discard_cmsg_resource(&arg.msg, 0);
395  "file descriptor was not passed (cmsg_len=%d, %d expected)",
396  (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));
397  }
398 #else
399  if (arg.msg.msg_accrightslen != sizeof(fd)) {
401  "file descriptor was not passed (accrightslen=%d, %d expected)",
402  arg.msg.msg_accrightslen, (int)sizeof(fd));
403  }
404 #endif
405 
406 #if FD_PASSING_BY_MSG_CONTROL
407  memcpy(&fd, CMSG_DATA(&cmsg.hdr), sizeof(int));
408 #endif
409 
410  rb_update_max_fd(fd);
411 
412  if (rsock_cmsg_cloexec_state < 0)
414  if (rsock_cmsg_cloexec_state == 0 || fd <= 2)
416 
417  if (klass == Qnil)
418  return INT2FIX(fd);
419  else {
420  ID for_fd;
421  int ff_argc;
422  VALUE ff_argv[2];
423  CONST_ID(for_fd, "for_fd");
424  ff_argc = mode == Qnil ? 1 : 2;
425  ff_argv[0] = INT2FIX(fd);
426  ff_argv[1] = mode;
427  return rb_funcallv(klass, for_fd, ff_argc, ff_argv);
428  }
429 }
430 #else
431 #define unix_recv_io rb_f_notimplement
432 #endif
433 
434 /*
435  * call-seq:
436  * unixsocket.addr => [address_family, unix_path]
437  *
438  * Returns the local address as an array which contains
439  * address_family and unix_path.
440  *
441  * Example
442  * serv = UNIXServer.new("/tmp/sock")
443  * p serv.addr #=> ["AF_UNIX", "/tmp/sock"]
444  */
445 static VALUE
446 unix_addr(VALUE sock)
447 {
448  rb_io_t *fptr;
449  struct sockaddr_un addr;
450  socklen_t len = (socklen_t)sizeof addr;
451  socklen_t len0 = len;
452 
453  GetOpenFile(sock, fptr);
454 
455  if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
456  rsock_sys_fail_path("getsockname(2)", fptr->pathv);
457  if (len0 < len) len = len0;
458  return rsock_unixaddr(&addr, len);
459 }
460 
461 /*
462  * call-seq:
463  * unixsocket.peeraddr => [address_family, unix_path]
464  *
465  * Returns the remote address as an array which contains
466  * address_family and unix_path.
467  *
468  * Example
469  * serv = UNIXServer.new("/tmp/sock")
470  * c = UNIXSocket.new("/tmp/sock")
471  * p c.peeraddr #=> ["AF_UNIX", "/tmp/sock"]
472  */
473 static VALUE
474 unix_peeraddr(VALUE sock)
475 {
476  rb_io_t *fptr;
477  struct sockaddr_un addr;
478  socklen_t len = (socklen_t)sizeof addr;
479  socklen_t len0 = len;
480 
481  GetOpenFile(sock, fptr);
482 
483  if (getpeername(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
484  rsock_sys_fail_path("getpeername(2)", fptr->pathv);
485  if (len0 < len) len = len0;
486  return rsock_unixaddr(&addr, len);
487 }
488 
489 /*
490  * call-seq:
491  * UNIXSocket.pair([type [, protocol]]) => [unixsocket1, unixsocket2]
492  * UNIXSocket.socketpair([type [, protocol]]) => [unixsocket1, unixsocket2]
493  *
494  * Creates a pair of sockets connected to each other.
495  *
496  * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc.
497  *
498  * _protocol_ should be a protocol defined in the domain.
499  * 0 is default protocol for the domain.
500  *
501  * s1, s2 = UNIXSocket.pair
502  * s1.send "a", 0
503  * s1.send "b", 0
504  * p s2.recv(10) #=> "ab"
505  *
506  */
507 static VALUE
508 unix_s_socketpair(int argc, VALUE *argv, VALUE klass)
509 {
510  VALUE domain, type, protocol;
511  VALUE args[3];
512 
513  domain = INT2FIX(PF_UNIX);
514  rb_scan_args(argc, argv, "02", &type, &protocol);
515  if (argc == 0)
516  type = INT2FIX(SOCK_STREAM);
517  if (argc <= 1)
518  protocol = INT2FIX(0);
519 
520  args[0] = domain;
521  args[1] = type;
522  args[2] = protocol;
523 
524  return rsock_sock_s_socketpair(3, args, klass);
525 }
526 #endif
527 
528 void
530 {
531 #ifdef HAVE_SYS_UN_H
532  /*
533  * Document-class: UNIXSocket < BasicSocket
534  *
535  * UNIXSocket represents a UNIX domain stream client socket.
536  */
537  rb_cUNIXSocket = rb_define_class("UNIXSocket", rb_cBasicSocket);
538  rb_define_method(rb_cUNIXSocket, "initialize", unix_init, 1);
539  rb_define_method(rb_cUNIXSocket, "path", unix_path, 0);
540  rb_define_method(rb_cUNIXSocket, "addr", unix_addr, 0);
541  rb_define_method(rb_cUNIXSocket, "peeraddr", unix_peeraddr, 0);
542  rb_define_method(rb_cUNIXSocket, "recvfrom", unix_recvfrom, -1);
543  rb_define_method(rb_cUNIXSocket, "send_io", unix_send_io, 1);
544  rb_define_method(rb_cUNIXSocket, "recv_io", unix_recv_io, -1);
545  rb_define_singleton_method(rb_cUNIXSocket, "socketpair", unix_s_socketpair, -1);
546  rb_define_singleton_method(rb_cUNIXSocket, "pair", unix_s_socketpair, -1);
547 #endif
548 }
void rsock_init_unixsocket(void)
Definition: unixsocket.c:529
VALUE rsock_init_unixsock(VALUE sock, VALUE path, int server)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:992
void rb_update_max_fd(int fd)
Definition: io.c:191
VALUE rb_cBasicSocket
Definition: init.c:13
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1716
int rsock_cmsg_cloexec_state
Definition: ancdata.c:5
int sendmsg(int, const struct msghdr *, int)
Definition: win32.c:3654
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:821
Definition: io.h:62
Definition: win32.h:206
VALUE rsock_init_sock(VALUE sock, int fd)
Definition: init.c:60
#define FIXNUM_P(f)
Definition: ruby.h:365
#define GetOpenFile(obj, fp)
Definition: io.h:120
VALUE rb_eArgError
Definition: error.c:802
VALUE rb_obj_is_kind_of(VALUE, VALUE)
call-seq: obj.is_a?(class) -> true or false obj.kind_of?(class) -> true or false
Definition: object.c:842
#define MEMZERO(p, type, n)
Definition: ruby.h:1660
VALUE rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
#define val
void rsock_syserr_fail_path(int err, const char *mesg, VALUE path)
Definition: socket.c:41
int rsock_socket(int domain, int type, int proto)
Definition: init.c:357
#define NIL_P(v)
Definition: ruby.h:451
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:646
int fd
Definition: io.h:64
int rb_io_wait_writable(int)
Definition: io.c:1132
int argc
Definition: ruby.c:187
RUBY_EXTERN VALUE rb_cIO
Definition: ruby.h:1913
#define RSTRING_LEN(str)
Definition: ruby.h:971
int errno
int socklen_t
Definition: getaddrinfo.c:83
VALUE rb_obj_freeze(VALUE)
call-seq: obj.freeze -> obj
Definition: object.c:1331
VALUE rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
Definition: init.c:146
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4309
unsigned long ID
Definition: ruby.h:86
#define Qnil
Definition: ruby.h:438
unsigned long VALUE
Definition: ruby.h:85
int rsock_detect_cloexec(int fd)
Definition: init.c:284
VALUE rb_eTypeError
Definition: error.c:801
#define FIX2INT(x)
Definition: ruby.h:686
Definition: win32.h:202
VALUE rb_str_dup(VALUE)
Definition: string.c:1488
#define rb_funcallv
Definition: console.c:21
register unsigned int len
Definition: zonetab.h:51
#define RSTRING_PTR(str)
Definition: ruby.h:975
VALUE rb_eSocket
Definition: init.c:25
#define INT2FIX(i)
Definition: ruby.h:232
int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
Definition: init.c:454
VALUE pathv
Definition: io.h:68
#define SafeStringValue(v)
Definition: ruby.h:574
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1158
void rsock_sys_fail_path(const char *mesg, VALUE path)
Definition: socket.c:35
#define CONST_ID(var, str)
Definition: ruby.h:1743
#define SOMAXCONN
Definition: constdefs.h:1849
#define NULL
Definition: _sdbm.c:102
int rb_io_wait_readable(int)
Definition: io.c:1106
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
#define BLOCKING_REGION_FD(func, arg)
Definition: rubysocket.h:262
void rb_maygvl_fd_fix_cloexec(int fd)
Definition: io.c:210
char ** argv
Definition: ruby.c:188