VirtualBox

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

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

need to wrap fopen as well.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.6 KB
Line 
1/* $Id: restartable-syscall-wrappers.c 2445 2011-07-07 10:20:24Z 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 <dlfcn.h>
41#include <errno.h>
42#include <fcntl.h>
43#include <stdarg.h>
44#include <stddef.h>
45#include <stdio.h>
46
47
48/*******************************************************************************
49* Defined Constants And Macros *
50*******************************************************************************/
51/** Mangle a syscall name to it's weak alias. */
52#ifdef KBUILD_OS_SOLARIS
53# define WRAP(a_name) _##a_name
54#elif defined(KBUILD_OS_LINUX)
55# define WRAP(a_name) __##a_name
56#else
57# error "Port Me"
58#endif
59
60/** Optional '64' suffix string for dlsym. */
61#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
62# define SYM_64_SUFFIX "64"
63#else
64# define SYM_64_SUFFIX ""
65#endif
66
67/** Mangle a syscall name with optional '64' suffix. */
68#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
69# define WRAP64(a_name) WRAP(a_name)##64
70#else
71# define WRAP64(a_name) WRAP(a_name)
72#endif
73
74/** Check whether errno indicates restart. */
75#ifdef ERESTART
76# define SHOULD_RESTART() (errno == EINTR || errno == ERESTART)
77#else
78# define SHOULD_RESTART() (errno == EINTR)
79#endif
80
81
82extern int WRAP64(open)(const char *pszName, int fFlags, ...);
83int open(const char *pszName, int fFlags, ...)
84{
85 mode_t fMode;
86 va_list va;
87 int fd;
88
89 va_start(va, fFlags);
90 fMode = va_arg(va, mode_t);
91 va_end(va);
92
93 do
94 fd = WRAP64(open)(pszName, fFlags, fMode);
95 while (fd == -1 && SHOULD_RESTART());
96 return fd;
97}
98
99
100#if !defined(KBUILD_OS_LINUX) /* no wrapper */
101extern int WRAP(mkdir)(const char *pszName, mode_t fMode);
102int mkdir(const char *pszName, mode_t fMode)
103{
104 int rc;
105 do
106 rc = WRAP(mkdir)(pszName, fMode);
107 while (rc == -1 && SHOULD_RESTART());
108 return rc;
109}
110#endif
111
112extern int WRAP64(stat)(const char *pszName, struct stat *pStBuf);
113int stat(const char *pszName, struct stat *pStBuf)
114{
115 int rc;
116 do
117 rc = WRAP64(stat)(pszName, pStBuf);
118 while (rc == -1 && SHOULD_RESTART());
119 return rc;
120}
121
122extern int WRAP64(lstat)(const char *pszName, struct stat *pStBuf);
123int lstat(const char *pszName, struct stat *pStBuf)
124{
125 int rc;
126 do
127 rc = WRAP64(lstat)(pszName, pStBuf);
128 while (rc == -1 && SHOULD_RESTART());
129 return rc;
130}
131
132extern ssize_t WRAP(read)(int fd, void *pvBuf, size_t cbBuf);
133ssize_t read(int fd, void *pvBuf, size_t cbBuf)
134{
135 ssize_t cbRead;
136 do
137 cbRead = WRAP(read)(fd, pvBuf, cbBuf);
138 while (cbRead == -1 && SHOULD_RESTART());
139 return cbRead;
140}
141
142extern ssize_t WRAP(write)(int fd, void *pvBuf, size_t cbBuf);
143ssize_t write(int fd, void *pvBuf, size_t cbBuf)
144{
145 ssize_t cbWritten;
146 do
147 cbWritten = WRAP(write)(fd, pvBuf, cbBuf);
148 while (cbWritten == -1 && SHOULD_RESTART());
149 return cbWritten;
150}
151
152static int dlsym_libc(const char *pszSymbol, void **ppvSym)
153{
154 static void *s_pvLibc = NULL;
155 void *pvLibc;
156 void *pvSym;
157
158 /*
159 * Open libc.
160 */
161 pvLibc = s_pvLibc;
162 if (!pvLibc)
163 {
164#ifdef RTLD_NOLOAD
165 pvLibc = dlopen("/libc/libc.so", RTLD_NOLOAD);
166#else
167 pvLibc = dlopen("/libc/libc.so", RTLD_GLOBAL);
168#endif
169 if (!pvLibc)
170 {
171 fprintf(stderr, "restartable-syscall-wrappers: failed to dlopen libc for resolving %s: %s\n",
172 pszSymbol, dlerror());
173 errno = ENOSYS;
174 return -1;
175 }
176 /** @todo check standard symbol? */
177 }
178
179 /*
180 * Resolve the symbol.
181 */
182 pvSym = dlsym(pvLibc, pszSymbol);
183 if (!pvSym)
184 {
185 fprintf(stderr, "restartable-syscall-wrappers: failed to resolve %s: %s\n",
186 pszSymbol, dlerror());
187 errno = ENOSYS;
188 return -1;
189 }
190
191 *ppvSym = pvSym;
192 return 0;
193}
194
195FILE *fopen(const char *pszName, const char *pszMode)
196{
197 static union
198 {
199 FILE *(* pfnFopen)(const char *, const char *);
200 void *pvSym;
201 } s_u;
202 FILE *pFile;
203
204 if ( !s_u.pfnFopen
205 && dlsym_libc("fopen" SYM_64_SUFFIX, &s_u.pvSym) != 0)
206 return NULL;
207
208 do
209 pFile = s_u.pfnFopen(pszName, pszMode);
210 while (!pFile && SHOULD_RESTART());
211 return pFile;
212}
213
214/** @todo chmod, chown, chgrp, times, and possible some more. */
215
216
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