VirtualBox

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

Last change on this file since 2707 was 2507, checked in by bird, 13 years ago

restartable-syscall-wrappers.c: Fixed open and open64 wrappers.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.9 KB
Line 
1/* $Id: restartable-syscall-wrappers.c 2507 2011-07-24 15:42:39Z 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 knut st. osmundsen <[email protected]>
16 *
17 * This file is part of kBuild.
18 *
19 * kBuild is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 3 of the License, or
22 * (at your option) any later version.
23 *
24 * kBuild is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with kBuild. If not, see <http://www.gnu.org/licenses/>
31 *
32 */
33
34
35/*******************************************************************************
36* Header Files *
37*******************************************************************************/
38#include <sys/types.h>
39#ifdef KBUILD_OS_SOLARIS
40# include <string.h> /* Try drag in feature_tests.h. */
41# include <ctype.h>
42# undef _RESTRICT_KYWD
43# define _RESTRICT_KYWD
44# undef __PRAGMA_REDEFINE_EXTNAME
45#endif
46#include <sys/stat.h>
47#include <utime.h>
48#include <dlfcn.h>
49#include <errno.h>
50#include <fcntl.h>
51#include <stdarg.h>
52#include <stddef.h>
53#include <stdio.h>
54
55
56/*******************************************************************************
57* Defined Constants And Macros *
58*******************************************************************************/
59/** Mangle a syscall name to it's weak alias. */
60#ifdef KBUILD_OS_SOLARIS
61# define WRAP(a_name) _##a_name
62#elif defined(KBUILD_OS_LINUX)
63# define WRAP(a_name) __##a_name
64#else
65# error "Port Me"
66#endif
67
68/** Mangle a syscall name with optional '64' suffix. */
69#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
70# define WRAP64(a_name) WRAP(a_name)##64
71#else
72# define WRAP64(a_name) WRAP(a_name)
73#endif
74
75/** Check whether errno indicates restart. */
76#ifdef ERESTART
77# define SHOULD_RESTART() (errno == EINTR || errno == ERESTART)
78#else
79# define SHOULD_RESTART() (errno == EINTR)
80#endif
81
82/** Used by XSTR. */
83#define XSTR_INNER(x) #x
84/** Returns the expanded argument as a string. */
85#define XSTR(x) XSTR_INNER(x)
86
87
88static int dlsym_libc(const char *pszSymbol, void **ppvSym)
89{
90 static void *s_pvLibc = NULL;
91 void *pvLibc;
92 void *pvSym;
93
94 /*
95 * Use the RTLD_NEXT dl feature if present, it's designed for doing
96 * exactly what we want here.
97 */
98#ifdef RTLD_NEXT
99 pvSym = dlsym(RTLD_NEXT, pszSymbol);
100 if (pvSym)
101 {
102 *ppvSym = pvSym;
103 return 0;
104 }
105#endif
106
107 /*
108 * Open libc.
109 */
110 pvLibc = s_pvLibc;
111 if (!pvLibc)
112 {
113#ifdef RTLD_NOLOAD
114 unsigned fFlags = RTLD_NOLOAD | RTLD_NOW;
115#else
116 unsigned fFlags = RTLD_GLOBAL | RTLD_NOW;
117#endif
118#ifdef KBUILD_OS_LINUX
119 pvLibc = dlopen("/lib/libc.so.6", fFlags);
120#else
121 pvLibc = dlopen("/lib/libc.so", fFlags);
122#endif
123 if (!pvLibc)
124 {
125 fprintf(stderr, "restartable-syscall-wrappers: failed to dlopen libc for resolving %s: %s\n",
126 pszSymbol, dlerror());
127 errno = ENOSYS;
128 return -1;
129 }
130 /** @todo check standard symbol? */
131 }
132
133 /*
134 * Resolve the symbol.
135 */
136 pvSym = dlsym(pvLibc, pszSymbol);
137 if (!pvSym)
138 {
139 fprintf(stderr, "restartable-syscall-wrappers: failed to resolve %s: %s\n",
140 pszSymbol, dlerror());
141 errno = ENOSYS;
142 return -1;
143 }
144
145 *ppvSym = pvSym;
146 return 0;
147}
148
149
150#undef open
151int open(const char *pszPath, int fFlags, ...)
152{
153 mode_t fMode;
154 va_list va;
155 int fd;
156 static union
157 {
158 int (* pfnReal)(const char *, int, ...);
159 void *pvSym;
160 } s_u;
161
162 if ( !s_u.pfnReal
163 && dlsym_libc("open", &s_u.pvSym) != 0)
164 return -1;
165
166 va_start(va, fFlags);
167 fMode = va_arg(va, mode_t);
168 va_end(va);
169
170 do
171 fd = s_u.pfnReal(pszPath, fFlags, fMode);
172 while (fd == -1 && SHOULD_RESTART());
173 return fd;
174}
175
176#undef open64
177int open64(const char *pszPath, int fFlags, ...)
178{
179 mode_t fMode;
180 va_list va;
181 int fd;
182 static union
183 {
184 int (* pfnReal)(const char *, int, ...);
185 void *pvSym;
186 } s_u;
187
188 if ( !s_u.pfnReal
189 && dlsym_libc("open64", &s_u.pvSym) != 0)
190 return -1;
191
192 va_start(va, fFlags);
193 fMode = va_arg(va, mode_t);
194 va_end(va);
195
196 do
197 fd = s_u.pfnReal(pszPath, fFlags, fMode);
198 while (fd == -1 && SHOULD_RESTART());
199 return fd;
200}
201
202#define WRAP_FN(a_Name, a_ParamsWithTypes, a_ParamsNoType, a_RetType, a_RetFailed) \
203 a_RetType a_Name a_ParamsWithTypes \
204 { \
205 static union \
206 { \
207 a_RetType (* pfnReal) a_ParamsWithTypes; \
208 void *pvSym; \
209 } s_u; \
210 a_RetType rc; \
211 \
212 if ( !s_u.pfnReal \
213 && dlsym_libc(#a_Name, &s_u.pvSym) != 0) \
214 return a_RetFailed; \
215 \
216 do \
217 rc = s_u.pfnReal a_ParamsNoType; \
218 while (rc == a_RetFailed && SHOULD_RESTART()); \
219 return rc; \
220 } typedef int ignore_semi_colon_##a_Name
221
222#undef mkdir
223WRAP_FN(mkdir, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
224
225#undef rmdir
226WRAP_FN(rmdir, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
227
228#undef unlink
229WRAP_FN(unlink, (const char *pszPath), (pszPath), int, -1);
230
231#undef remove
232WRAP_FN(remove, (const char *pszPath), (pszPath), int, -1);
233
234#undef symlink
235WRAP_FN(symlink, (const char *pszFrom, const char *pszTo), (pszFrom, pszTo), int, -1);
236
237#undef link
238WRAP_FN(link, (const char *pszFrom, const char *pszTo), (pszFrom, pszTo), int, -1);
239
240#undef stat
241WRAP_FN(stat, (const char *pszPath, struct stat *pStBuf), (pszPath, pStBuf), int, -1);
242#undef lstat
243WRAP_FN(lstat, (const char *pszPath, struct stat *pStBuf), (pszPath, pStBuf), int, -1);
244
245#undef stat64
246WRAP_FN(stat64, (const char *pszPath, struct stat64 *pStBuf), (pszPath, pStBuf), int, -1);
247#undef lstat64
248WRAP_FN(lstat64, (const char *pszPath, struct stat64 *pStBuf), (pszPath, pStBuf), int, -1);
249
250#undef read
251WRAP_FN(read, (int fd, void *pvBuf, size_t cbBuf), (fd, pvBuf, cbBuf), ssize_t, -1);
252
253#undef write
254WRAP_FN(write, (int fd, void *pvBuf, size_t cbBuf), (fd, pvBuf, cbBuf), ssize_t, -1);
255
256#undef fopen
257WRAP_FN(fopen, (const char *pszPath, const char *pszMode), (pszPath, pszMode), FILE *, NULL);
258#undef fopen64
259WRAP_FN(fopen64, (const char *pszPath, const char *pszMode), (pszPath, pszMode), FILE *, NULL);
260
261#undef chmod
262WRAP_FN(chmod, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
263#undef lchmod
264WRAP_FN(lchmod, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
265
266#undef chown
267WRAP_FN(chown, (const char *pszPath, uid_t uid, gid_t gid), (pszPath, uid, gid), int, -1);
268#undef lchown
269WRAP_FN(lchown, (const char *pszPath, uid_t uid, gid_t gid), (pszPath, uid, gid), int, -1);
270
271#undef utime
272WRAP_FN(utime, (const char *pszPath, const struct utimbuf *pTimes), (pszPath, pTimes), int, -1);
273
274#undef utimes
275WRAP_FN(utimes, (const char *pszPath, const struct timeval *paTimes), (pszPath, paTimes), int, -1);
276
277#undef pathconf
278WRAP_FN(pathconf, (const char *pszPath, int iCfgNm), (pszPath, iCfgNm), long, -1);
279
280#undef readlink
281WRAP_FN(readlink, (const char *pszPath, char *pszBuf, size_t cbBuf), (pszPath, pszBuf, cbBuf), ssize_t, -1);
282
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