From aaa0e88d55abcddfdf895508b86fe18e3d6b5cea Mon Sep 17 00:00:00 2001
From: Eric Wong <normalperson@yhbt.net>
Date: Fri, 3 Jan 2014 07:20:29 +0000
Subject: [PATCH] socket: preserve errno before rb_sys_fail_* and friends

rb_sprintf and other methods may clear errno.
Preserve it and reset it immediately before rb_sys_fail* functions.
---
 ext/socket/socket.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index 5fd7465..c968598 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -16,12 +16,14 @@ void
 rsock_sys_fail_host_port(const char *mesg, VALUE host, VALUE port)
 {
     VALUE message;
+    int err = errno;
 
     port = rb_String(port);
 
     message = rb_sprintf("%s for \"%s\" port %s",
 	    mesg, StringValueCStr(host), StringValueCStr(port));
 
+    errno = err;
     rb_sys_fail_str(message);
 }
 
@@ -29,6 +31,8 @@ void
 rsock_sys_fail_path(const char *mesg, VALUE path)
 {
     VALUE message;
+    int err = errno;
+
     if (RB_TYPE_P(path, T_STRING)) {
         if (memchr(RSTRING_PTR(path), '\0', RSTRING_LEN(path))) {
             path = rb_str_inspect(path);
@@ -39,6 +43,7 @@ rsock_sys_fail_path(const char *mesg, VALUE path)
             message = rb_sprintf("%s for \"%s\"", mesg,
                     StringValueCStr(path));
         }
+        errno = err;
         rb_sys_fail_str(message);
     }
     else {
@@ -50,9 +55,11 @@ void
 rsock_sys_fail_sockaddr(const char *mesg, struct sockaddr *addr, socklen_t len)
 {
     VALUE rai;
+    int err = errno;
 
     rai = rsock_addrinfo_new(addr, len, PF_UNSPEC, 0, 0, Qnil, Qnil);
 
+    errno = err;
     rsock_sys_fail_raddrinfo(mesg, rai);
 }
 
@@ -60,18 +67,24 @@ void
 rsock_sys_fail_raddrinfo(const char *mesg, VALUE rai)
 {
     VALUE str, message;
+    int err = errno;
 
     str = rsock_addrinfo_inspect_sockaddr(rai);
     message = rb_sprintf("%s for %s", mesg, StringValueCStr(str));
 
+    errno = err;
     rb_sys_fail_str(message);
 }
 
 void
 rsock_sys_fail_raddrinfo_or_sockaddr(const char *mesg, VALUE addr, VALUE rai)
 {
+    int err = errno;
+
     if (NIL_P(rai)) {
         StringValue(addr);
+
+        errno = err;
         rsock_sys_fail_sockaddr(mesg,
             (struct sockaddr *)RSTRING_PTR(addr),
             (socklen_t)RSTRING_LEN(addr)); /* overflow should be checked already */
-- 
1.8.5.2.193.g2394e94

