You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
1
(22) |
2
(19) |
3
(8) |
4
(34) |
5
(14) |
6
(14) |
|
7
(12) |
8
(15) |
9
(15) |
10
(10) |
11
(10) |
12
(28) |
13
(11) |
|
14
(22) |
15
(29) |
16
(20) |
17
(15) |
18
(39) |
19
(11) |
20
(12) |
|
21
(8) |
22
(9) |
23
(8) |
24
(10) |
25
(9) |
26
(7) |
27
(7) |
|
28
(6) |
29
(6) |
30
(11) |
|
|
|
|
|
From: Tom H. <th...@cy...> - 2004-11-24 23:53:04
|
CVS commit by thughes:
Yet another attempt to make the pthre cancellation wrappers work.
The exact search order followed by RTLD_NEXT and RTLD_DEFAULT seems to be
very variable across different glibc releases, especially when the pthread
library is pulled in implicitly by a dependency in another library.
As a result I have now given up on that scheme and have resorted to the
simple tactic of explicitly opening libc.so and then looking for the
function to forward to through that handle.
MERGE TO STABLE
M +58 -45 vg_libpthread.c 1.161.2.3
--- valgrind/coregrind/vg_libpthread.c #1.161.2.2:1.161.2.3
@@ -2243,17 +2243,34 @@ void ** (*__libc_internal_tsd_address)
------------------------------------------------------------------ */
-static void *libpthread_handle;
+static void *get_libc_handle(void)
+{
+ static void *libc_handle = NULL;
-#define FORWARD(name, altname, args...) \
+ if (libc_handle == NULL) {
+ libc_handle = dlopen("libc.so.6", RTLD_LAZY);
+ my_assert(libc_handle != NULL);
+ }
+
+ return libc_handle;
+}
+
+static void *get_libpthread_handle(void)
+{
+ static void *libpthread_handle = NULL;
+
+ if (libpthread_handle == NULL) {
+ libpthread_handle = dlopen("libpthread.so.0", RTLD_LAZY);
+ my_assert(libpthread_handle != NULL);
+ }
+
+ return libpthread_handle;
+}
+
+#define FORWARD(name, args...) \
({ \
static name##_t name##_ptr = NULL; \
- if (libpthread_handle == NULL) { \
- libpthread_handle = dlopen("libpthread.so.0", RTLD_LAZY); \
- my_assert(libpthread_handle != NULL); \
- } \
if (name##_ptr == NULL) { \
- if ((name##_ptr = (name##_t)dlsym(RTLD_NEXT, #name)) == NULL) \
- name##_ptr = (name##_t)dlsym(RTLD_DEFAULT, #altname); \
- my_assert(name##_ptr != NULL && name##_ptr != dlsym(libpthread_handle, #name)); \
+ name##_ptr = (name##_t)dlsym(get_libc_handle(), #name); \
+ my_assert(name##_ptr != NULL && name##_ptr != dlsym(get_libpthread_handle(), #name)); \
} \
name##_ptr(args); \
@@ -2270,9 +2287,5 @@ int sigaction(int signum,
{
__my_pthread_testcancel();
-#ifdef GLIBC_2_1
- return FORWARD(sigaction, __sigaction, signum, act, oldact);
-#else
- return FORWARD(sigaction, __libc_sigaction, signum, act, oldact);
-#endif
+ return FORWARD(sigaction, signum, act, oldact);
}
@@ -2284,5 +2297,5 @@ int accept(int fd, struct sockaddr *addr
{
__my_pthread_testcancel();
- return FORWARD(accept, __libc_accept, fd, addr, len);
+ return FORWARD(accept, fd, addr, len);
}
@@ -2297,5 +2310,5 @@ int connect(int sockfd,
{
__my_pthread_testcancel();
- return FORWARD(connect, __libc_connect, sockfd, serv_addr, addrlen);
+ return FORWARD(connect, sockfd, serv_addr, addrlen);
}
@@ -2307,5 +2320,5 @@ int fcntl(int fd, int cmd, long arg)
{
__my_pthread_testcancel();
- return FORWARD(fcntl, __libc_fcntl, fd, cmd, arg);
+ return FORWARD(fcntl, fd, cmd, arg);
}
@@ -2317,5 +2330,5 @@ ssize_t write(int fd, const void *buf, s
{
__my_pthread_testcancel();
- return FORWARD(write, __libc_write, fd, buf, count);
+ return FORWARD(write, fd, buf, count);
}
@@ -2327,5 +2340,5 @@ ssize_t read(int fd, void *buf, size_t c
{
__my_pthread_testcancel();
- return FORWARD(read, __libc_read, fd, buf, count);
+ return FORWARD(read, fd, buf, count);
}
@@ -2335,5 +2348,5 @@ int (*open64_t)(const char *pathname, in
int open64(const char *pathname, int flags, mode_t mode)
{
- return FORWARD(open64, __libc_open64, pathname, flags, mode);
+ return FORWARD(open64, pathname, flags, mode);
}
@@ -2343,5 +2356,5 @@ int (*open_t)(const char *pathname, int
int open(const char *pathname, int flags, mode_t mode)
{
- return FORWARD(open, __libc_open, pathname, flags, mode);
+ return FORWARD(open, pathname, flags, mode);
}
@@ -2352,5 +2365,5 @@ int close(int fd)
{
__my_pthread_testcancel();
- return FORWARD(close, __libc_close, fd);
+ return FORWARD(close, fd);
}
@@ -2362,5 +2375,5 @@ pid_t waitpid(pid_t pid, int *status, in
{
__my_pthread_testcancel();
- return FORWARD(waitpid, __libc_waitpid, pid, status, options);
+ return FORWARD(waitpid, pid, status, options);
}
@@ -2372,5 +2385,5 @@ int __nanosleep(const struct timespec *r
{
__my_pthread_testcancel();
- return FORWARD(__nanosleep, __libc_nanosleep, req, rem);
+ return FORWARD(__nanosleep, req, rem);
}
@@ -2381,5 +2394,5 @@ int pause(void)
{
__my_pthread_testcancel();
- return FORWARD(pause, __libc_pause);
+ return FORWARD(pause);
}
@@ -2391,5 +2404,5 @@ int __tcdrain(int fd)
{
__my_pthread_testcancel();
- return FORWARD(__tcdrain, __libc_tcdrain, fd);
+ return FORWARD(__tcdrain, fd);
}
@@ -2401,5 +2414,5 @@ int fsync(int fd)
{
__my_pthread_testcancel();
- return FORWARD(fsync, __libc_fsync, fd);
+ return FORWARD(fsync, fd);
}
@@ -2411,5 +2424,5 @@ off_t lseek(int fildes, off_t offset, in
{
__my_pthread_testcancel();
- return FORWARD(lseek, __libc_lseek, fildes, offset, whence);
+ return FORWARD(lseek, fildes, offset, whence);
}
@@ -2421,5 +2434,5 @@ __off64_t lseek64(int fildes, __off64_t
{
__my_pthread_testcancel();
- return FORWARD(lseek64, __libc_lseek64, fildes, offset, whence);
+ return FORWARD(lseek64, fildes, offset, whence);
}
@@ -2432,5 +2445,5 @@ ssize_t __pread64 (int __fd, void *__buf
{
__my_pthread_testcancel();
- return FORWARD(__pread64, __libc_pread64, __fd, __buf, __nbytes, __offset);
+ return FORWARD(__pread64, __fd, __buf, __nbytes, __offset);
}
@@ -2443,5 +2456,5 @@ ssize_t __pwrite64 (int __fd, const void
{
__my_pthread_testcancel();
- return FORWARD(__pwrite64, __libc_pwrite64, __fd, __buf, __nbytes, __offset);
+ return FORWARD(__pwrite64, __fd, __buf, __nbytes, __offset);
}
@@ -2453,5 +2466,5 @@ ssize_t pwrite(int fd, const void *buf,
{
__my_pthread_testcancel();
- return FORWARD(pwrite, __libc_pwrite, fd, buf, count, offset);
+ return FORWARD(pwrite, fd, buf, count, offset);
}
@@ -2463,5 +2476,5 @@ ssize_t pread(int fd, void *buf, size_t
{
__my_pthread_testcancel();
- return FORWARD(pread, __libc_pread, fd, buf, count, offset);
+ return FORWARD(pread, fd, buf, count, offset);
}
@@ -2472,5 +2485,5 @@ int recv(int s, void *msg, size_t len, i
{
__my_pthread_testcancel();
- return FORWARD(recv, __libc_recv, s, msg, len, flags);
+ return FORWARD(recv, s, msg, len, flags);
}
@@ -2481,5 +2494,5 @@ int send(int s, const void *msg, size_t
{
__my_pthread_testcancel();
- return FORWARD(send, __libc_send, s, msg, len, flags);
+ return FORWARD(send, s, msg, len, flags);
}
@@ -2491,5 +2504,5 @@ int sendmsg(int s, const struct msghdr *
{
__my_pthread_testcancel();
- return FORWARD(sendmsg, __libc_sendmsg, s, msg, flags);
+ return FORWARD(sendmsg, s, msg, flags);
}
@@ -2501,5 +2514,5 @@ int recvmsg(int s, struct msghdr *msg, i
{
__my_pthread_testcancel();
- return FORWARD(recvmsg, __libc_recvmsg, s, msg, flags);
+ return FORWARD(recvmsg, s, msg, flags);
}
@@ -2513,5 +2526,5 @@ int recvfrom(int s, void *buf, size_t le
{
__my_pthread_testcancel();
- return FORWARD(recvfrom, __libc_recfrom, s, buf, len, flags, from, fromlen);
+ return FORWARD(recvfrom, s, buf, len, flags, from, fromlen);
}
@@ -2525,5 +2538,5 @@ int sendto(int s, const void *msg, size_
{
__my_pthread_testcancel();
- return FORWARD(sendto, __libc_sendto, s, msg, len, flags, to, tolen);
+ return FORWARD(sendto, s, msg, len, flags, to, tolen);
}
@@ -2535,5 +2548,5 @@ int system(const char* str)
{
__my_pthread_testcancel();
- return FORWARD(system, __libc_system, str);
+ return FORWARD(system, str);
}
@@ -2545,5 +2558,5 @@ pid_t wait(int *status)
{
__my_pthread_testcancel();
- return FORWARD(wait, __libc_wait, status);
+ return FORWARD(wait, status);
}
@@ -2555,5 +2568,5 @@ int msync(const void *start, size_t leng
{
__my_pthread_testcancel();
- return FORWARD(msync, __libc_msync, start, length, flags);
+ return FORWARD(msync, start, length, flags);
}
@@ -2581,5 +2594,5 @@ void (*longjmp_t)(jmp_buf env, int val)
void longjmp(jmp_buf env, int val)
{
- FORWARD(longjmp, __libc_longjmp, env, val);
+ FORWARD(longjmp, env, val);
}
@@ -2590,5 +2603,5 @@ void siglongjmp(sigjmp_buf env, int val)
{
kludged("siglongjmp", "(it ignores cleanup handlers)");
- FORWARD(siglongjmp, __libc_siglongjmp, env, val);
+ FORWARD(siglongjmp, env, val);
}
@@ -2652,5 +2665,5 @@ pid_t __fork(void)
run_fork_handlers(0 /* prepare */);
- pid = FORWARD(__fork, __libc_fork);
+ pid = FORWARD(__fork);
if (pid == 0) {
/* I am the child */
|
|
From: Tom H. <th...@cy...> - 2004-11-24 23:51:54
|
CVS commit by thughes:
Yet another attempt to make the pthre cancellation wrappers work.
The exact search order followed by RTLD_NEXT and RTLD_DEFAULT seems to be
very variable across different glibc releases, especially when the pthread
library is pulled in implicitly by a dependency in another library.
As a result I have now given up on that scheme and have resorted to the
simple tactic of explicitly opening libc.so and then looking for the
function to forward to through that handle.
M +58 -45 vg_libpthread.c 1.179
--- valgrind/coregrind/vg_libpthread.c #1.178:1.179
@@ -2246,17 +2246,34 @@ void ** (*__libc_internal_tsd_address)
------------------------------------------------------------------ */
-static void *libpthread_handle;
+static void *get_libc_handle(void)
+{
+ static void *libc_handle = NULL;
-#define FORWARD(name, altname, args...) \
+ if (libc_handle == NULL) {
+ libc_handle = dlopen("libc.so.6", RTLD_LAZY);
+ my_assert(libc_handle != NULL);
+ }
+
+ return libc_handle;
+}
+
+static void *get_libpthread_handle(void)
+{
+ static void *libpthread_handle = NULL;
+
+ if (libpthread_handle == NULL) {
+ libpthread_handle = dlopen("libpthread.so.0", RTLD_LAZY);
+ my_assert(libpthread_handle != NULL);
+ }
+
+ return libpthread_handle;
+}
+
+#define FORWARD(name, args...) \
({ \
static name##_t name##_ptr = NULL; \
- if (libpthread_handle == NULL) { \
- libpthread_handle = dlopen("libpthread.so.0", RTLD_LAZY); \
- my_assert(libpthread_handle != NULL); \
- } \
if (name##_ptr == NULL) { \
- if ((name##_ptr = (name##_t)dlsym(RTLD_NEXT, #name)) == NULL) \
- name##_ptr = (name##_t)dlsym(RTLD_DEFAULT, #altname); \
- my_assert(name##_ptr != NULL && name##_ptr != dlsym(libpthread_handle, #name)); \
+ name##_ptr = (name##_t)dlsym(get_libc_handle(), #name); \
+ my_assert(name##_ptr != NULL && name##_ptr != dlsym(get_libpthread_handle(), #name)); \
} \
name##_ptr(args); \
@@ -2273,9 +2290,5 @@ int sigaction(int signum,
{
__my_pthread_testcancel();
-#ifdef GLIBC_2_1
- return FORWARD(sigaction, __sigaction, signum, act, oldact);
-#else
- return FORWARD(sigaction, __libc_sigaction, signum, act, oldact);
-#endif
+ return FORWARD(sigaction, signum, act, oldact);
}
@@ -2287,5 +2300,5 @@ int accept(int fd, struct sockaddr *addr
{
__my_pthread_testcancel();
- return FORWARD(accept, __libc_accept, fd, addr, len);
+ return FORWARD(accept, fd, addr, len);
}
@@ -2300,5 +2313,5 @@ int connect(int sockfd,
{
__my_pthread_testcancel();
- return FORWARD(connect, __libc_connect, sockfd, serv_addr, addrlen);
+ return FORWARD(connect, sockfd, serv_addr, addrlen);
}
@@ -2310,5 +2323,5 @@ int fcntl(int fd, int cmd, long arg)
{
__my_pthread_testcancel();
- return FORWARD(fcntl, __libc_fcntl, fd, cmd, arg);
+ return FORWARD(fcntl, fd, cmd, arg);
}
@@ -2320,5 +2333,5 @@ ssize_t write(int fd, const void *buf, s
{
__my_pthread_testcancel();
- return FORWARD(write, __libc_write, fd, buf, count);
+ return FORWARD(write, fd, buf, count);
}
@@ -2330,5 +2343,5 @@ ssize_t read(int fd, void *buf, size_t c
{
__my_pthread_testcancel();
- return FORWARD(read, __libc_read, fd, buf, count);
+ return FORWARD(read, fd, buf, count);
}
@@ -2338,5 +2351,5 @@ int (*open64_t)(const char *pathname, in
int open64(const char *pathname, int flags, mode_t mode)
{
- return FORWARD(open64, __libc_open64, pathname, flags, mode);
+ return FORWARD(open64, pathname, flags, mode);
}
@@ -2346,5 +2359,5 @@ int (*open_t)(const char *pathname, int
int open(const char *pathname, int flags, mode_t mode)
{
- return FORWARD(open, __libc_open, pathname, flags, mode);
+ return FORWARD(open, pathname, flags, mode);
}
@@ -2355,5 +2368,5 @@ int close(int fd)
{
__my_pthread_testcancel();
- return FORWARD(close, __libc_close, fd);
+ return FORWARD(close, fd);
}
@@ -2365,5 +2378,5 @@ pid_t waitpid(pid_t pid, int *status, in
{
__my_pthread_testcancel();
- return FORWARD(waitpid, __libc_waitpid, pid, status, options);
+ return FORWARD(waitpid, pid, status, options);
}
@@ -2375,5 +2388,5 @@ int __nanosleep(const struct timespec *r
{
__my_pthread_testcancel();
- return FORWARD(__nanosleep, __libc_nanosleep, req, rem);
+ return FORWARD(__nanosleep, req, rem);
}
@@ -2384,5 +2397,5 @@ int pause(void)
{
__my_pthread_testcancel();
- return FORWARD(pause, __libc_pause);
+ return FORWARD(pause);
}
@@ -2394,5 +2407,5 @@ int __tcdrain(int fd)
{
__my_pthread_testcancel();
- return FORWARD(__tcdrain, __libc_tcdrain, fd);
+ return FORWARD(__tcdrain, fd);
}
@@ -2404,5 +2417,5 @@ int fsync(int fd)
{
__my_pthread_testcancel();
- return FORWARD(fsync, __libc_fsync, fd);
+ return FORWARD(fsync, fd);
}
@@ -2414,5 +2427,5 @@ off_t lseek(int fildes, off_t offset, in
{
__my_pthread_testcancel();
- return FORWARD(lseek, __libc_lseek, fildes, offset, whence);
+ return FORWARD(lseek, fildes, offset, whence);
}
@@ -2424,5 +2437,5 @@ __off64_t lseek64(int fildes, __off64_t
{
__my_pthread_testcancel();
- return FORWARD(lseek64, __libc_lseek64, fildes, offset, whence);
+ return FORWARD(lseek64, fildes, offset, whence);
}
@@ -2435,5 +2448,5 @@ ssize_t __pread64 (int __fd, void *__buf
{
__my_pthread_testcancel();
- return FORWARD(__pread64, __libc_pread64, __fd, __buf, __nbytes, __offset);
+ return FORWARD(__pread64, __fd, __buf, __nbytes, __offset);
}
@@ -2446,5 +2459,5 @@ ssize_t __pwrite64 (int __fd, const void
{
__my_pthread_testcancel();
- return FORWARD(__pwrite64, __libc_pwrite64, __fd, __buf, __nbytes, __offset);
+ return FORWARD(__pwrite64, __fd, __buf, __nbytes, __offset);
}
@@ -2456,5 +2469,5 @@ ssize_t pwrite(int fd, const void *buf,
{
__my_pthread_testcancel();
- return FORWARD(pwrite, __libc_pwrite, fd, buf, count, offset);
+ return FORWARD(pwrite, fd, buf, count, offset);
}
@@ -2466,5 +2479,5 @@ ssize_t pread(int fd, void *buf, size_t
{
__my_pthread_testcancel();
- return FORWARD(pread, __libc_pread, fd, buf, count, offset);
+ return FORWARD(pread, fd, buf, count, offset);
}
@@ -2475,5 +2488,5 @@ ssize_t recv(int s, void *msg, size_t le
{
__my_pthread_testcancel();
- return FORWARD(recv, __libc_recv, s, msg, len, flags);
+ return FORWARD(recv, s, msg, len, flags);
}
@@ -2484,5 +2497,5 @@ ssize_t send(int s, const void *msg, siz
{
__my_pthread_testcancel();
- return FORWARD(send, __libc_send, s, msg, len, flags);
+ return FORWARD(send, s, msg, len, flags);
}
@@ -2494,5 +2507,5 @@ ssize_t sendmsg(int s, const struct msgh
{
__my_pthread_testcancel();
- return FORWARD(sendmsg, __libc_sendmsg, s, msg, flags);
+ return FORWARD(sendmsg, s, msg, flags);
}
@@ -2504,5 +2517,5 @@ ssize_t recvmsg(int s, struct msghdr *ms
{
__my_pthread_testcancel();
- return FORWARD(recvmsg, __libc_recvmsg, s, msg, flags);
+ return FORWARD(recvmsg, s, msg, flags);
}
@@ -2516,5 +2529,5 @@ ssize_t recvfrom(int s, void *buf, size_
{
__my_pthread_testcancel();
- return FORWARD(recvfrom, __libc_recfrom, s, buf, len, flags, from, fromlen);
+ return FORWARD(recvfrom, s, buf, len, flags, from, fromlen);
}
@@ -2528,5 +2541,5 @@ ssize_t sendto(int s, const void *msg, s
{
__my_pthread_testcancel();
- return FORWARD(sendto, __libc_sendto, s, msg, len, flags, to, tolen);
+ return FORWARD(sendto, s, msg, len, flags, to, tolen);
}
@@ -2538,5 +2551,5 @@ int system(const char* str)
{
__my_pthread_testcancel();
- return FORWARD(system, __libc_system, str);
+ return FORWARD(system, str);
}
@@ -2548,5 +2561,5 @@ pid_t wait(int *status)
{
__my_pthread_testcancel();
- return FORWARD(wait, __libc_wait, status);
+ return FORWARD(wait, status);
}
@@ -2558,5 +2571,5 @@ int msync(const void *start, size_t leng
{
__my_pthread_testcancel();
- return FORWARD(msync, __libc_msync, start, length, flags);
+ return FORWARD(msync, start, length, flags);
}
@@ -2584,5 +2597,5 @@ void (*longjmp_t)(jmp_buf env, int val)
void longjmp(jmp_buf env, int val)
{
- FORWARD(longjmp, __libc_longjmp, env, val);
+ FORWARD(longjmp, env, val);
}
@@ -2593,5 +2606,5 @@ void siglongjmp(sigjmp_buf env, int val)
{
kludged("siglongjmp", "(it ignores cleanup handlers)");
- FORWARD(siglongjmp, __libc_siglongjmp, env, val);
+ FORWARD(siglongjmp, env, val);
}
@@ -2655,5 +2668,5 @@ pid_t __fork(void)
run_fork_handlers(0 /* prepare */);
- pid = FORWARD(__fork, __libc_fork);
+ pid = FORWARD(__fork);
if (pid == 0) {
/* I am the child */
|
|
From: Jeremy F. <je...@go...> - 2004-11-24 19:25:15
|
On Wed, 2004-11-24 at 09:43 +0000, Nicholas Nethercote wrote: > > I agree we should acknowledge and try to fix the problems, but I'm > > basically pessimistic. The real problem is that 32-bits is just not > > enough address space for us. We need more. > > No -- 32 bits is not enough address space for FV. We can't ignore 32-bit > platforms just because they're more difficult than 64-bit platforms. We > have to balance conflicting constraints, and I think FV goes too far in > one direction. Yes, I understand that, but I think the intermingled scheme has a number of serious problems as well. It needs to use address space as well, there's no getting around that, and the question is whether its better to preallocate a chunk up front, or mingle it among the application's mappings, on an incremental basis. In both cases, the client can allocate the same amount of actual memory; the same number of pages are available. In the FV case, pages with addresses above a particular address are off limits. In the intermingled case, the off-limits pages are scattered among the client's mappings. So, aside from programs which actually need to use address X, where X is in Valgrind's part of the address space, what doesn't work in the FV case which does work in the intermingled case? The pressing problem is that V+memcheck more than doubles a program's memory use, and when a program starts using about as much memory as it has address space, that becomes a problem. That's why address space is a problem for Valgrind, regardless of how it actually uses it. > Oh come on, without FV the kernel is going to basically map things upwards > in a straight line from the mapbase; it's not going to put little maps > around randomly and cause fragmentation. Yes, it is. The kernel, by design, puts mmaps at random addresses as a security measure. You can work around it, but assuming that mmap isn't going to do that is non-portable, and just doesn't work for modern kernels. Even on older kernels, once the mmap area had been gone over once, the map placement was pretty random. Even if it did just mmap linearly up the address space, it's going to lead to bad fragmentation. After each client mapping you'd have a valgrind mapping, so that the memory layout looks like CVCVCVCVCV. If the client then removes all its mappings and wants to create one large one, then it will fail to find the memory, even though there should be enough. > The memory layout would be more > flexible, not less, because you wouldn't have the big-bang shadow area, > and you wouldn't have Valgrind occupying the top 0x10000000 bytes. Well, the flexibility is useful, but it's also a problem. It means that most stuff will work mostly, but it also means that the free address space is broken up in ways that the client (or the programmer trying to debug it) can't know about, anticipate, work around or understand. The location and size distribution of free address space will vary from run to run, possibly causing the client to work sometime and fail at others. > > What's worse, this could easily be non-deterministic from run to run, > > since the kernel could easily choose new places for the mappings. > > Why is that a problem? Well, because you'll end up with bug reports like: "My program ran for 2 hours before crashing with mmap failed. When I ran it again it crashed after only 10 minutes. It has been running now for 3 hours, but I don't know if it will finish (I expect it will take 10)". If the program only does small mmaps, then there probably won't be a problem, but as soon as it wants to do largeish (64Mbyte? 128Mbyte?) maps, virtual address space fragmentation will be a real, pressing issue. J |
|
From: Nicholas N. <nj...@ca...> - 2004-11-24 09:44:14
|
On Tue, 23 Nov 2004, Jeremy Fitzhardinge wrote: >> I rewrote the skip-list the other day to provide a much cleaner >> interface that avoids these strange behaviours. > > Oh, good. Can you describe it? See the attached diff, and a unit test file, which you have to put in the coregrind/ directory of a Valgrind tree, and built with something like this: gcc -c -g -I../include -I../include/x86 -Ix86 -I../include/x86-linux/ -I../include/linux -Ix86-linux -I.. s.c -fprofile-arcs -ftest-coverage gcc s.o -o a.out -fprofile-arcs -ftest-coverage The basic change is that the node compare function is now asymmetric -- it compares a node with a key, rather than two keys. This is necessary for doing ranges, because usually you're comparing an address against a range held by a segment. You can still use the data structre for normal non-range key/value tables too. >> Of course not. My proposal doesn't reduce the functionality at all, >> except for the strict client/Valgrind separation. What I object to is the >> use of techniques that are clever but fragile. Also, doing work that the >> kernel could do for us (ie. deciding where to put maps) is not good. > > Well, map placement is pretty straightforward. I disagree. You said yourself that the skiplist/segment stuff is messy and needs cleaning up. Remember also that you wrote that code; I look at it and get confused. And it's distributed complexity, which is a bad thing. > I agree we should acknowledge and try to fix the problems, but I'm > basically pessimistic. The real problem is that 32-bits is just not > enough address space for us. We need more. No -- 32 bits is not enough address space for FV. We can't ignore 32-bit platforms just because they're more difficult than 64-bit platforms. We have to balance conflicting constraints, and I think FV goes too far in one direction. > At the moment, the client gets a nice clear piece of address space which > it can do what it likes with: it can create large(-ish) mappings, > knowing that the space is clear; it can scan /proc/self/maps and see > only the mappings it created[*], knowing that it can create mappings in > the gaps. It can know where it has been placed, make assumptions about > what mappings in the address space exist, use MAP_FIXED, munmap, > mprotect without causing us any problems. If it tries to get out of its > address space, it fails exactly as if the kernel had given it a small > address space. > > With the intermingled scheme, we can handle the client making lots of > little maps all over the address space, but we're fragmenting the > client's address space. Programs which want to create large mappings > will be thwarted because there just aren't any more holes left in the > address space (these could get very small). Oh come on, without FV the kernel is going to basically map things upwards in a straight line from the mapbase; it's not going to put little maps around randomly and cause fragmentation. The memory layout would be more flexible, not less, because you wouldn't have the big-bang shadow area, and you wouldn't have Valgrind occupying the top 0x10000000 bytes. > What's worse, this could easily be non-deterministic from run to run, > since the kernel could easily choose new places for the mappings. Why is that a problem? N |
|
From: Tom H. <th...@cy...> - 2004-11-24 03:38:19
|
Nightly build on standard ( Red Hat 7.2 ) started at 2004-11-24 03:00:02 GMT Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow insn_fpu: valgrind ./insn_fpu insn_mmx: valgrind ./insn_mmx insn_mmxext: valgrind ./insn_mmxext insn_sse: valgrind ./insn_sse insn_sse2: (skipping, prereq failed: ../../../tests/cputest x86-sse2) int: valgrind ./int rm: cannot remove `vgcore.pid*': No such file or directory (cleanup operation failed: rm vgcore.pid*) pushpopseg: valgrind ./pushpopseg rcl_assert: valgrind ./rcl_assert seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 191 tests, 2 stderr failures, 0 stdout failures ================= memcheck/tests/scalar (stderr) memcheck/tests/vgtest_ume (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <to...@co...> - 2004-11-24 03:30:24
|
Nightly build on dunsmere ( Fedora Core 3 ) started at 2004-11-24 03:20:04 GMT Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 191 tests, 12 stderr failures, 1 stdout failure ================= corecheck/tests/fdleak_cmsg (stderr) corecheck/tests/fdleak_fcntl (stderr) corecheck/tests/fdleak_ipv4 (stderr) corecheck/tests/fdleak_socketpair (stderr) memcheck/tests/badpoll (stderr) memcheck/tests/buflen_check (stderr) memcheck/tests/execve (stderr) memcheck/tests/execve2 (stderr) memcheck/tests/scalar (stderr) memcheck/tests/scalar_exit_group (stderr) memcheck/tests/scalar_supp (stderr) memcheck/tests/writev (stderr) none/tests/exec-sigmask (stdout) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2004-11-24 03:21:02
|
Nightly build on audi ( Red Hat 9 ) started at 2004-11-24 03:15:03 GMT Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 191 tests, 12 stderr failures, 0 stdout failures ================= corecheck/tests/fdleak_cmsg (stderr) corecheck/tests/fdleak_fcntl (stderr) corecheck/tests/fdleak_ipv4 (stderr) corecheck/tests/fdleak_socketpair (stderr) memcheck/tests/badpoll (stderr) memcheck/tests/buflen_check (stderr) memcheck/tests/execve (stderr) memcheck/tests/execve2 (stderr) memcheck/tests/scalar (stderr) memcheck/tests/scalar_exit_group (stderr) memcheck/tests/scalar_supp (stderr) memcheck/tests/writev (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2004-11-24 03:15:28
|
Nightly build on ginetta ( Red Hat 8.0 ) started at 2004-11-24 03:10:02 GMT Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow insn_cmov: valgrind ./insn_cmov insn_fpu: valgrind ./insn_fpu insn_mmx: valgrind ./insn_mmx insn_mmxext: valgrind ./insn_mmxext insn_sse: valgrind ./insn_sse insn_sse2: (skipping, prereq failed: ../../../tests/cputest x86-sse2) int: valgrind ./int rm: cannot remove `vgcore.pid*': No such file or directory (cleanup operation failed: rm vgcore.pid*) pushpopseg: valgrind ./pushpopseg rcl_assert: valgrind ./rcl_assert seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 191 tests, 1 stderr failure, 0 stdout failures ================= memcheck/tests/scalar (stderr) make: *** [regtest] Error 1 |
|
From: Tom H. <th...@cy...> - 2004-11-24 03:10:58
|
Nightly build on alvis ( Red Hat 7.3 ) started at 2004-11-24 03:05:02 GMT Checking out source tree ... done Configuring ... done Building ... done Running regression tests ... done Last 20 lines of log.verbose follow insn_fpu: valgrind ./insn_fpu insn_mmx: valgrind ./insn_mmx insn_mmxext: valgrind ./insn_mmxext insn_sse: valgrind ./insn_sse insn_sse2: (skipping, prereq failed: ../../../tests/cputest x86-sse2) int: valgrind ./int rm: cannot remove `vgcore.pid*': No such file or directory (cleanup operation failed: rm vgcore.pid*) pushpopseg: valgrind ./pushpopseg rcl_assert: valgrind ./rcl_assert seg_override: valgrind ./seg_override -- Finished tests in none/tests/x86 ------------------------------------ yield: valgrind ./yield -- Finished tests in none/tests ---------------------------------------- == 191 tests, 2 stderr failures, 0 stdout failures ================= memcheck/tests/scalar (stderr) memcheck/tests/vgtest_ume (stderr) make: *** [regtest] Error 1 |
|
From: Jeremy F. <je...@go...> - 2004-11-24 00:01:00
|
On Mon, 2004-11-22 at 16:06 +0000, Nicholas Nethercote wrote:
> I don't think "reasonably sure" is good enough.
At the moment, in Valgrind as it stands, its "absolutely sure", because
we set the ulimit to prevent the kernel from paying attention to the brk
syscall.
In the larger scheme of things, memory allocators are *the* most
overridden class of functions in any libc; every malloc debugging
package needs to be able to do it. If we can't do it, then that's a
pretty severe libc bug on that platform.
BSD's libc makes it easy to intercept the brk syscall, which solves the
problem simply. glibc makes it hard, but not impossibly so. The
problem will need to be addressed in some way for each platform.
But the libc question is a digression.
> > But using system libraries wasn't the only reason to disentangle
> > ourselves from the dynamic linker.
>
> How does FV provide that independence?
The client and the Valgrind core are running completely separate
instances of ld.so. The client may not have an ld.so at all, or it may
be a completely different implementation from the core's. The point is
that the core uses ld.so like any other normal program would, and
doesn't rely on it performing special tricks or magic (or at all -
Valgrind could be statically linked if the target required it).
In the original scheme, we were relying on:
* ld.so starting Valgrind "early enough"
* the client and V running ld.so on both the virtual and real CPUs
* blind good luck that these would never happen at the same time
* the client not trashing the ld.so structures
The only reason it worked at all is that we used dlopen(, LD_BIND_NOW)
which stopped V from doing lazy incremental binding as it ran, but it's
putting a lot of faith in the dynamic linker to assume that that means
it will never run code on your behalf.
> > A bounds-limit test for each memory access isn't that expensive, and in
> > 64-bit address spaces, you can make the client address space a power of
> > 2 in size, which simplifies the test. You could also use a v. large
> > redzone to make hits much more unlikely. The segment test is nice
> > because it actually is free, but explicit testing probably isn't that
> > expensive, particularly if the codegen can remove redundant tests, and
> > schedule the tests it does generate appropriately.
>
> I'm not very keen on features that require greatly different mechanisms on
> different architectures.
Me neither. In this particular instance, it is something which is
arch-dependent anyway, and doesn't have widespread implications. For
CPU X, how do we generate a "bounds check pointer Y" operation"? It's
just a codegen question. Similarly, creating a redzone is just part of
"How do we lay out a process? What goes where?".
The bigger problem is handing shadow memory access. The current scheme
can't be scaled to a larger address space simply - at the very least you
need to add an extra layer of page table. Once you have that, you need
to work out how to abstract "shadow memory access" so that the every
tool doesn't need to know about how to do it, which in turn means that
your options are wider.
The nice thing about a lare shadow mapping is that it does naturally
scale unchanged from 32-bit to 64-bit address spaces, because we use the
CPU's own mapping hardware to do the expensive/tricky parts. The
downside is that it uses too much virtual address space on 32-bit
machines. The "manual" pagetable scheme is better for virtual address
space use, but it flat out doesn't scale to 64-bits at all.
> Julian made a good point about distinguishing between read-only and
> read-write memory with Memcheck/Addrcheck. Also, my proposal doesn't
> preclude Valgrind from keeping it's own copy of ld.so, as is done now.
Yeah, that would have to be a prerequisite for it to be a workable
scheme.
I guess you could keep them separate, but you'd still need to stage1/2
system, and a specially linked Valgrind to make sure that as V
initializes it doesn't start occupying the client's address space.
> I rewrote the skip-list the other day to provide a much cleaner
> interface that avoids these strange behaviours.
Oh, good. Can you describe it?
> several of the places that use the
> skip-list functions do so in such a difficult-to-understand way that I was
> unable to determine for a number of them if they were buggy, or doing
> something extremely subtle
Yeah, that needs cleaning up.
> There's also a nasty 7-function cycle in the
> memory allocation stuff which Julian stumbled across
Yep, that stuff is always tricky.
> Of course not. My proposal doesn't reduce the functionality at all,
> except for the strict client/Valgrind separation. What I object to is the
> use of techniques that are clever but fragile. Also, doing work that the
> kernel could do for us (ie. deciding where to put maps) is not good.
Well, map placement is pretty straightforward. It seems to me that if
we can use the CPU's pagetable hardware directly, that's a bigger
complexity/performance win, and if the cost is doing our own placement,
that's a fair tradeoff. Even aside from that, I think pointercheck is a
pretty important thing in its own right.
> Like Julian said, people writing programs that have strict memory limits.
> A couple of people have recently asked for a --mem-limit option, because
> they cannot use ulimit to restrict memory sizes.
Eh? That's different. They want to be able to restrict the client's
memory allocation. That doesn't mean that Valgrind itself is
constrained in how much memory it can use. And as I said to Julian,
embedded systems have physical memory limits, not virtual.
> Of course I can't prove it. But I do think that Valgrind crashes with
> random, unexplained seg faults more than it used to. There are a quite a
> lot of bugs in Bugzilla like that. Some of them have been dealt with
> since I made FV more strict about checking the results of mmap(), etc, but
> we still get them.
My concern is that allowing the client to trash Valgrind's memory will
increase the incidence of unexplainable bugs rather than decrease them.
> FV is a nice idea, but
> practice has shown us that it ultimately is flawed. There's no shame in
> that, but it's not a good idea to ignore these flaws.
I agree we should acknowledge and try to fix the problems, but I'm
basically pessimistic. The real problem is that 32-bits is just not
enough address space for us. We need more. After all, both schemes use
the same amount of physical memory; this is just a question of how
virtual address space gets used. With, say, memcheck, a process which
approaches using 1.5Gbytes of memory (in a 3G user space) is going to
run out of memory either way.
I also think the implied process memory model created by the
intermingled scheme presents a lot of problems.
At the moment, the client gets a nice clear piece of address space which
it can do what it likes with: it can create large(-ish) mappings,
knowing that the space is clear; it can scan /proc/self/maps and see
only the mappings it created[*], knowing that it can create mappings in
the gaps. It can know where it has been placed, make assumptions about
what mappings in the address space exist, use MAP_FIXED, munmap,
mprotect without causing us any problems. If it tries to get out of its
address space, it fails exactly as if the kernel had given it a small
address space.
With the intermingled scheme, we can handle the client making lots of
little maps all over the address space, but we're fragmenting the
client's address space. Programs which want to create large mappings
will be thwarted because there just aren't any more holes left in the
address space (these could get very small). What's worse, this could
easily be non-deterministic from run to run, since the kernel could
easily choose new places for the mappings.
If a process does a mmap/munmap/mprotect, we have to make sure it
doesn't hit any Valgrind mappings, and work out what a sane response is
if it does. There's no analogy in the normal operation of the kernel
(since we're effectively creating a discontiguous address space), so we
need to invent a discontiguous process memory model and its semantics.
[ * - not implemented yet ]
So if I can summarize:
FV - pros:
* Valgrind protected from the client
* Client gets clear, flat address space
cons:
* static allocation of the address spaces limits client address
space size
* construction of address space mappings can fail on some systems
* code complexity in managing mappings, and separating address
spaces
Intermingled - pros:
* flexible address space layout handles clients with lots of small
sparse mappings
* no large mmaps or other tricky allocations
cons:
* introduces discontigious process memory model
* code complexity in protecting valgrind mmaps
* valgrind unprotected from client
* non-deterministic process layout and address space fragmentation
J
|