VirtualBox

source: kBuild/trunk/src/lib/restartable-syscall-wrappers.c@ 2851

Last change on this file since 2851 was 2851, checked in by bird, 9 years ago

updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.4 KB
Line 
1/* $Id: restartable-syscall-wrappers.c 2851 2016-08-31 17:30:52Z bird $ */
2/** @file
3 * restartable-syscall-wrappers.c - Workaround for annoying S11 "features".
4 *
5 * The symptoms are that open or mkdir occationally fails with EINTR when
6 * receiving SIGCHLD at the wrong time. With a enough cores, this start
7 * happening on a regular basis.
8 *
9 * The workaround here is to create our own wrappers for these syscalls which
10 * will restart the syscall when appropriate. This depends on the libc
11 * providing alternative names for the syscall entry points.
12 */
13
14/*
15 * Copyright (c) 2011-2016 knut st. osmundsen <[email protected]>
16 *
17 * Permission is hereby granted, free of charge, to any person obtaining a
18 * copy of this software and associated documentation files (the "Software"),
19 * to deal in the Software without restriction, including without limitation
20 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21 * and/or sell copies of the Software, and to permit persons to whom the
22 * Software is furnished to do so, subject to the following conditions:
23 *
24 * The above copyright notice and this permission notice shall be included
25 * in all copies or substantial portions of the Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
33 * IN THE SOFTWARE.
34 *
35 * Alternatively, the content of this file may be used under the terms of the
36 * GPL version 2 or later, or LGPL version 2.1 or later.
37 */
38
39
40/*******************************************************************************
41* Header Files *
42*******************************************************************************/
43#include <sys/types.h>
44#ifdef KBUILD_OS_SOLARIS
45# include <string.h> /* Try drag in feature_tests.h. */
46# include <ctype.h>
47# undef _RESTRICT_KYWD
48# define _RESTRICT_KYWD
49# undef __PRAGMA_REDEFINE_EXTNAME
50#endif
51#include <sys/stat.h>
52#include <utime.h>
53#include <dlfcn.h>
54#include <errno.h>
55#include <fcntl.h>
56#include <stdarg.h>
57#include <stddef.h>
58#include <stdio.h>
59
60
61/*******************************************************************************
62* Defined Constants And Macros *
63*******************************************************************************/
64/** Mangle a syscall name to it's weak alias. */
65#ifdef KBUILD_OS_SOLARIS
66# define WRAP(a_name) _##a_name
67#elif defined(KBUILD_OS_LINUX)
68# define WRAP(a_name) __##a_name
69#else
70# error "Port Me"
71#endif
72
73/** Mangle a syscall name with optional '64' suffix. */
74#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
75# define WRAP64(a_name) WRAP(a_name)##64
76#else
77# define WRAP64(a_name) WRAP(a_name)
78#endif
79
80/** Check whether errno indicates restart. */
81#ifdef ERESTART
82# define SHOULD_RESTART() (errno == EINTR || errno == ERESTART)
83#else
84# define SHOULD_RESTART() (errno == EINTR)
85#endif
86
87/** Used by XSTR. */
88#define XSTR_INNER(x) #x
89/** Returns the expanded argument as a string. */
90#define XSTR(x) XSTR_INNER(x)
91
92
93static int dlsym_libc(const char *pszSymbol, void **ppvSym)
94{
95 static void *s_pvLibc = NULL;
96 void *pvLibc;
97 void *pvSym;
98
99 /*
100 * Use the RTLD_NEXT dl feature if present, it's designed for doing
101 * exactly what we want here.
102 */
103#ifdef RTLD_NEXT
104 pvSym = dlsym(RTLD_NEXT, pszSymbol);
105 if (pvSym)
106 {
107 *ppvSym = pvSym;
108 return 0;
109 }
110#endif
111
112 /*
113 * Open libc.
114 */
115 pvLibc = s_pvLibc;
116 if (!pvLibc)
117 {
118#ifdef RTLD_NOLOAD
119 unsigned fFlags = RTLD_NOLOAD | RTLD_NOW;
120#else
121 unsigned fFlags = RTLD_GLOBAL | RTLD_NOW;
122#endif
123#ifdef KBUILD_OS_LINUX
124 pvLibc = dlopen("/lib/libc.so.6", fFlags);
125#else
126 pvLibc = dlopen("/lib/libc.so", fFlags);
127#endif
128 if (!pvLibc)
129 {
130 fprintf(stderr, "restartable-syscall-wrappers: failed to dlopen libc for resolving %s: %s\n",
131 pszSymbol, dlerror());
132 errno = ENOSYS;
133 return -1;
134 }
135 /** @todo check standard symbol? */
136 }
137
138 /*
139 * Resolve the symbol.
140 */
141 pvSym = dlsym(pvLibc, pszSymbol);
142 if (!pvSym)
143 {
144 fprintf(stderr, "restartable-syscall-wrappers: failed to resolve %s: %s\n",
145 pszSymbol, dlerror());
146 errno = ENOSYS;
147 return -1;
148 }
149
150 *ppvSym = pvSym;
151 return 0;
152}
153
154
155#undef open
156int open(const char *pszPath, int fFlags, ...)
157{
158 mode_t fMode;
159 va_list va;
160 int fd;
161 static union
162 {
163 int (* pfnReal)(const char *, int, ...);
164 void *pvSym;
165 } s_u;
166
167 if ( !s_u.pfnReal
168 && dlsym_libc("open", &s_u.pvSym) != 0)
169 return -1;
170
171 va_start(va, fFlags);
172 fMode = va_arg(va, mode_t);
173 va_end(va);
174
175 do
176 fd = s_u.pfnReal(pszPath, fFlags, fMode);
177 while (fd == -1 && SHOULD_RESTART());
178 return fd;
179}
180
181#undef open64
182int open64(const char *pszPath, int fFlags, ...)
183{
184 mode_t fMode;
185 va_list va;
186 int fd;
187 static union
188 {
189 int (* pfnReal)(const char *, int, ...);
190 void *pvSym;
191 } s_u;
192
193 if ( !s_u.pfnReal
194 && dlsym_libc("open64", &s_u.pvSym) != 0)
195 return -1;
196
197 va_start(va, fFlags);
198 fMode = va_arg(va, mode_t);
199 va_end(va);
200
201 do
202 fd = s_u.pfnReal(pszPath, fFlags, fMode);
203 while (fd == -1 && SHOULD_RESTART());
204 return fd;
205}
206
207#define WRAP_FN(a_Name, a_ParamsWithTypes, a_ParamsNoType, a_RetType, a_RetFailed) \
208 a_RetType a_Name a_ParamsWithTypes \
209 { \
210 static union \
211 { \
212 a_RetType (* pfnReal) a_ParamsWithTypes; \
213 void *pvSym; \
214 } s_u; \
215 a_RetType rc; \
216 \
217 if ( !s_u.pfnReal \
218 && dlsym_libc(#a_Name, &s_u.pvSym) != 0) \
219 return a_RetFailed; \
220 \
221 do \
222 rc = s_u.pfnReal a_ParamsNoType; \
223 while (rc == a_RetFailed && SHOULD_RESTART()); \
224 return rc; \
225 } typedef int ignore_semi_colon_##a_Name
226
227#undef mkdir
228WRAP_FN(mkdir, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
229
230#undef rmdir
231WRAP_FN(rmdir, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
232
233#undef unlink
234WRAP_FN(unlink, (const char *pszPath), (pszPath), int, -1);
235
236#undef remove
237WRAP_FN(remove, (const char *pszPath), (pszPath), int, -1);
238
239#undef symlink
240WRAP_FN(symlink, (const char *pszFrom, const char *pszTo), (pszFrom, pszTo), int, -1);
241
242#undef link
243WRAP_FN(link, (const char *pszFrom, const char *pszTo), (pszFrom, pszTo), int, -1);
244
245#undef stat
246WRAP_FN(stat, (const char *pszPath, struct stat *pStBuf), (pszPath, pStBuf), int, -1);
247#undef lstat
248WRAP_FN(lstat, (const char *pszPath, struct stat *pStBuf), (pszPath, pStBuf), int, -1);
249
250#undef stat64
251WRAP_FN(stat64, (const char *pszPath, struct stat64 *pStBuf), (pszPath, pStBuf), int, -1);
252#undef lstat64
253WRAP_FN(lstat64, (const char *pszPath, struct stat64 *pStBuf), (pszPath, pStBuf), int, -1);
254
255#undef read
256WRAP_FN(read, (int fd, void *pvBuf, size_t cbBuf), (fd, pvBuf, cbBuf), ssize_t, -1);
257
258#undef write
259WRAP_FN(write, (int fd, void *pvBuf, size_t cbBuf), (fd, pvBuf, cbBuf), ssize_t, -1);
260
261#undef fopen
262WRAP_FN(fopen, (const char *pszPath, const char *pszMode), (pszPath, pszMode), FILE *, NULL);
263#undef fopen64
264WRAP_FN(fopen64, (const char *pszPath, const char *pszMode), (pszPath, pszMode), FILE *, NULL);
265
266#undef chmod
267WRAP_FN(chmod, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
268#undef lchmod
269WRAP_FN(lchmod, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
270
271#undef chown
272WRAP_FN(chown, (const char *pszPath, uid_t uid, gid_t gid), (pszPath, uid, gid), int, -1);
273#undef lchown
274WRAP_FN(lchown, (const char *pszPath, uid_t uid, gid_t gid), (pszPath, uid, gid), int, -1);
275
276#undef utime
277WRAP_FN(utime, (const char *pszPath, const struct utimbuf *pTimes), (pszPath, pTimes), int, -1);
278
279#undef utimes
280WRAP_FN(utimes, (const char *pszPath, const struct timeval *paTimes), (pszPath, paTimes), int, -1);
281
282#undef pathconf
283WRAP_FN(pathconf, (const char *pszPath, int iCfgNm), (pszPath, iCfgNm), long, -1);
284
285#undef readlink
286WRAP_FN(readlink, (const char *pszPath, char *pszBuf, size_t cbBuf), (pszPath, pszBuf, cbBuf), ssize_t, -1);
287
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette