Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

unix-socket: do not let close() or chdir() clobber errno during cleanup

unix_stream_connect and unix_stream_listen return -1 on error, with
errno set by the failing underlying call to allow the caller to write
a useful diagnosis.

Unfortunately the error path involves a few system calls itself, such
as close(), that can themselves touch errno.

This is not as worrisome as it might sound.  If close() fails, this
just means substituting one meaningful error message for another,
which is perfectly fine.  However, when the call _succeeds_, it is
allowed to (and sometimes might) clobber errno along the way with some
undefined value, so it is good higiene to save errno and restore it
immediately before returning to the caller.  Do so.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information...
commit 06121a0a8328c8aaa7a023cf6ebb142e9dc2b45c 1 parent 8ec6c8d
jrn jrn authored committed

Showing 1 changed file with 22 additions and 17 deletions. Show diff stats Hide diff stats

  1. +22 17 unix-socket.c
39 unix-socket.c
@@ -73,25 +73,29 @@ static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
73 73
74 74 int unix_stream_connect(const char *path)
75 75 {
76   - int fd;
  76 + int fd, saved_errno;
77 77 struct sockaddr_un sa;
78 78 struct unix_sockaddr_context ctx;
79 79
80 80 if (unix_sockaddr_init(&sa, path, &ctx) < 0)
81 81 return -1;
82 82 fd = unix_stream_socket();
83   - if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
84   - unix_sockaddr_cleanup(&ctx);
85   - close(fd);
86   - return -1;
87   - }
  83 + if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
  84 + goto fail;
88 85 unix_sockaddr_cleanup(&ctx);
89 86 return fd;
  87 +
  88 +fail:
  89 + saved_errno = errno;
  90 + unix_sockaddr_cleanup(&ctx);
  91 + close(fd);
  92 + errno = saved_errno;
  93 + return -1;
90 94 }
91 95
92 96 int unix_stream_listen(const char *path)
93 97 {
94   - int fd;
  98 + int fd, saved_errno;
95 99 struct sockaddr_un sa;
96 100 struct unix_sockaddr_context ctx;
97 101
@@ -100,18 +104,19 @@ int unix_stream_listen(const char *path)
100 104 fd = unix_stream_socket();
101 105
102 106 unlink(path);
103   - if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
104   - unix_sockaddr_cleanup(&ctx);
105   - close(fd);
106   - return -1;
107   - }
  107 + if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
  108 + goto fail;
108 109
109   - if (listen(fd, 5) < 0) {
110   - unix_sockaddr_cleanup(&ctx);
111   - close(fd);
112   - return -1;
113   - }
  110 + if (listen(fd, 5) < 0)
  111 + goto fail;
114 112
115 113 unix_sockaddr_cleanup(&ctx);
116 114 return fd;
  115 +
  116 +fail:
  117 + saved_errno = errno;
  118 + unix_sockaddr_cleanup(&ctx);
  119 + close(fd);
  120 + errno = saved_errno;
  121 + return -1;
117 122 }

Git Notes

amlog

Message-Id: <20120111235009.GB30243@burratino>

0 comments on commit 06121a0

Please sign in to comment.
Something went wrong with that request. Please try again.