VirtualBox

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

Last change on this file since 2468 was 2468, checked in by bird, 14 years ago

restartable-syscall-wrappers.c: Redid the wrapping to make sure we cover the ones with the '64' suffix as well as the ones without it.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.6 KB
Line 
1/* $Id: restartable-syscall-wrappers.c 2468 2011-07-12 12:50:50Z 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#include <sys/stat.h>
40#include <utime.h>
41#include <dlfcn.h>
42#include <errno.h>
43#include <fcntl.h>
44#include <stdarg.h>
45#include <stddef.h>
46#ifdef KBUILD_OS_SOLARIS
47# undef __PRAGMA_REDEFINE_EXTNAME
48#endif
49#include <stdio.h>
50
51
52/*******************************************************************************
53* Defined Constants And Macros *
54*******************************************************************************/
55/** Mangle a syscall name to it's weak alias. */
56#ifdef KBUILD_OS_SOLARIS
57# define WRAP(a_name) _##a_name
58#elif defined(KBUILD_OS_LINUX)
59# define WRAP(a_name) __##a_name
60#else
61# error "Port Me"
62#endif
63
64/** Mangle a syscall name with optional '64' suffix. */
65#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
66# define WRAP64(a_name) WRAP(a_name)##64
67#else
68# define WRAP64(a_name) WRAP(a_name)
69#endif
70
71/** Check whether errno indicates restart. */
72#ifdef ERESTART
73# define SHOULD_RESTART() (errno == EINTR || errno == ERESTART)
74#else
75# define SHOULD_RESTART() (errno == EINTR)
76#endif
77
78/** Used by XSTR. */
79#define XSTR_INNER(x) #x
80/** Returns the expanded argument as a string. */
81#define XSTR(x) XSTR_INNER(x)
82
83
84static int dlsym_libc(const char *pszSymbol, void **ppvSym)
85{
86 static void *s_pvLibc = NULL;
87 void *pvLibc;
88 void *pvSym;
89
90 /*
91 * Use the RTLD_NEXT dl feature if present, it's designed for doing
92 * exactly what we want here.
93 */
94#ifdef RTLD_NEXT
95 pvSym = dlsym(RTLD_NEXT, pszSymbol);
96 if (pvSym)
97 {
98 *ppvSym = pvSym;
99 return 0;
100 }
101#endif
102
103 /*
104 * Open libc.
105 */
106 pvLibc = s_pvLibc;
107 if (!pvLibc)
108 {
109#ifdef RTLD_NOLOAD
110 unsigned fFlags = RTLD_NOLOAD | RTLD_NOW;
111#else
112 unsigned fFlags = RTLD_GLOBAL | RTLD_NOW;
113#endif
114#ifdef KBUILD_OS_LINUX
115 pvLibc = dlopen("/lib/libc.so.6", fFlags);
116#else
117 pvLibc = dlopen("/lib/libc.so", fFlags);
118#endif
119 if (!pvLibc)
120 {
121 fprintf(stderr, "restartable-syscall-wrappers: failed to dlopen libc for resolving %s: %s\n",
122 pszSymbol, dlerror());
123 errno = ENOSYS;
124 return -1;
125 }
126 /** @todo check standard symbol? */
127 }
128
129 /*
130 * Resolve the symbol.
131 */
132 pvSym = dlsym(pvLibc, pszSymbol);
133 if (!pvSym)
134 {
135 fprintf(stderr, "restartable-syscall-wrappers: failed to resolve %s: %s\n",
136 pszSymbol, dlerror());
137 errno = ENOSYS;
138 return -1;
139 }
140
141 *ppvSym = pvSym;
142 return 0;
143}
144
145
146
147int open(const char *pszPath, int fFlags, ...)
148{
149 mode_t fMode;
150 va_list va;
151 int fd;
152 static union
153 {
154 int (* pfnReal)(const char *, int, mode_t);
155 void *pvSym;
156 } s_u;
157
158 if ( !s_u.pfnReal
159 && dlsym_libc("open", &s_u.pvSym) != 0)
160 return -1;
161
162 va_start(va, fFlags);
163 fMode = va_arg(va, mode_t);
164 va_end(va);
165
166 do
167 fd = s_u.pfnReal(pszPath, fFlags, fMode);
168 while (fd == -1 && SHOULD_RESTART());
169 return fd;
170}
171
172int open64(const char *pszPath, int fFlags, ...)
173{
174 mode_t fMode;
175 va_list va;
176 int fd;
177 static union
178 {
179 int (* pfnReal)(const char *, int, mode_t);
180 void *pvSym;
181 } s_u;
182
183 if ( !s_u.pfnReal
184 && dlsym_libc("open64", &s_u.pvSym) != 0)
185 return -1;
186
187 va_start(va, fFlags);
188 fMode = va_arg(va, mode_t);
189 va_end(va);
190
191 do
192 fd = s_u.pfnReal(pszPath, fFlags, fMode);
193 while (fd == -1 && SHOULD_RESTART());
194 return fd;
195}
196
197#define WRAP_FN(a_Name, a_ParamsWithTypes, a_ParamsNoType, a_RetType, a_RetFailed) \
198 a_RetType a_Name a_ParamsWithTypes \
199 { \
200 static union \
201 { \
202 a_RetType (* pfnReal) a_ParamsWithTypes; \
203 void *pvSym; \
204 } s_u; \
205 a_RetType rc; \
206 \
207 if ( !s_u.pfnReal \
208 && dlsym_libc(#a_Name, &s_u.pvSym) != 0) \
209 return a_RetFailed; \
210 \
211 do \
212 rc = s_u.pfnReal a_ParamsNoType; \
213 while (rc == a_RetFailed && SHOULD_RESTART()); \
214 return rc; \
215 } typedef int ignore_semi_colon_##a_Name
216
217#undef mkdir
218WRAP_FN(mkdir, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
219
220#undef rmdir
221WRAP_FN(rmdir, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
222
223#undef unlink
224WRAP_FN(unlink, (const char *pszPath), (pszPath), int, -1);
225
226#undef remove
227WRAP_FN(remove, (const char *pszPath), (pszPath), int, -1);
228
229#undef symlink
230WRAP_FN(symlink, (const char *pszFrom, const char *pszTo), (pszFrom, pszTo), int, -1);
231
232#undef link
233WRAP_FN(link, (const char *pszFrom, const char *pszTo), (pszFrom, pszTo), int, -1);
234
235#undef stat
236WRAP_FN(stat, (const char *pszPath, struct stat *pStBuf), (pszPath, pStBuf), int, -1);
237#undef stat64
238WRAP_FN(stat64, (const char *pszPath, struct stat *pStBuf), (pszPath, pStBuf), int, -1);
239
240#undef lstat
241WRAP_FN(lstat, (const char *pszPath, struct stat *pStBuf), (pszPath, pStBuf), int, -1);
242#undef lstat64
243WRAP_FN(lstat64, (const char *pszPath, struct stat *pStBuf), (pszPath, pStBuf), int, -1);
244
245#undef read
246WRAP_FN(read, (int fd, void *pvBuf, size_t cbBuf), (fd, pvBuf, cbBuf), ssize_t, -1);
247
248#undef write
249WRAP_FN(write, (int fd, void *pvBuf, size_t cbBuf), (fd, pvBuf, cbBuf), ssize_t, -1);
250
251#undef fopen
252WRAP_FN(fopen, (const char *pszPath, const char *pszMode), (pszPath, pszMode), FILE *, NULL);
253#undef fopen64
254WRAP_FN(fopen64, (const char *pszPath, const char *pszMode), (pszPath, pszMode), FILE *, NULL);
255
256#undef chmod
257WRAP_FN(chmod, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
258#undef lchmod
259WRAP_FN(lchmod, (const char *pszPath, mode_t fMode), (pszPath, fMode), int, -1);
260
261#undef chown
262WRAP_FN(chown, (const char *pszPath, uid_t uid, gid_t gid), (pszPath, uid, gid), int, -1);
263#undef lchown
264WRAP_FN(lchown, (const char *pszPath, uid_t uid, gid_t gid), (pszPath, uid, gid), int, -1);
265
266#undef utime
267WRAP_FN(utime, (const char *pszPath, const struct utimbuf *pTimes), (pszPath, pTimes), int, -1);
268
269#undef utimes
270WRAP_FN(utimes, (const char *pszPath, const struct timeval *paTimes), (pszPath, paTimes), int, -1);
271
272#undef pathconf
273WRAP_FN(pathconf, (const char *pszPath, int iCfgNm), (pszPath, iCfgNm), long, -1);
274
275
Note: See TracBrowser for help on using the repository browser.

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