1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
#include "stdafx.h"
#include "Debug.h"
#if defined(CHECK_SYSCALLS) && defined(POSIX)
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/wait.h>
/**
* Monitor system calls. Sometimes we get a EINTR during initialization of Gtk+ that kills the
* entire initialization process. With this contraption, we might see where it comes from.
*/
template <class R, class ... T>
class SyscallCheck {
public:
SyscallCheck(const char *name) : name(name), called(0) {
prev = (Prev)dlsym(RTLD_NEXT, name);
assert(prev);
}
R operator ()(T ... args) {
atomicIncrement(called);
R result = (*prev)(args...);
if (result < 0 && errno == EINTR) {
PLN(L"EINTR caught after calling " << name << " for " << called << L" times.");
perror(name);
errno = EINTR;
}
return result;
}
private:
typedef R (*Prev)(T...);
Prev prev;
size_t called;
const char *name;
};
/**
* These should be all system calls that can return EINTR that are interesting to us.
*/
ssize_t SHARED_EXPORT read(int fd, void *buf, size_t count) {
static SyscallCheck<ssize_t, int, void *, size_t> prev("read");
return prev(fd, buf, count);
}
ssize_t SHARED_EXPORT readv(int fd, const struct iovec *iov, int count) {
static SyscallCheck<ssize_t, int, const struct iovec *, int> prev("readv");
return prev(fd, iov, count);
}
ssize_t SHARED_EXPORT write(int fd, const void *buf, size_t count) {
static SyscallCheck<ssize_t, int, const void *, size_t> prev("write");
return prev(fd, buf, count);
}
ssize_t SHARED_EXPORT writev(int fd, const struct iovec *iov, int count) {
static SyscallCheck<ssize_t, int, const struct iovec *, int> prev("writev");
return prev(fd, iov, count);
}
// NOTE: Can not do 'ioctl', 'open'...
pid_t SHARED_EXPORT wait(int *stat) {
static SyscallCheck<pid_t, int *> prev("wait");
return prev(stat);
}
pid_t SHARED_EXPORT waitpid(pid_t pid, int *stat, int opts) {
static SyscallCheck<pid_t, pid_t, int *, int> prev("waitpid");
return prev(pid, stat, opts);
}
int SHARED_EXPORT waitid(idtype_t idtype, id_t id, siginfo_t *info, int opts) {
static SyscallCheck<int, idtype_t, id_t, siginfo_t *, int> prev("waitid");
return prev(idtype, id, info, opts);
}
// NOTE: wait3 and wait4 seem obsolete, and therefore ignored at the moment.
int SHARED_EXPORT accept(int socket, struct sockaddr *addr, socklen_t *len) {
static SyscallCheck<int, int, struct sockaddr *, socklen_t *> prev("accept");
return prev(socket, addr, len);
}
int SHARED_EXPORT connect(int socket, const struct sockaddr *addr, socklen_t len) {
static SyscallCheck<int, int, const struct sockaddr *, socklen_t> prev("connect");
return prev(socket, addr, len);
}
ssize_t SHARED_EXPORT recv(int socket, void *buffer, size_t len, int flags) {
static SyscallCheck<ssize_t, int, void *, size_t, int> prev("recv");
return prev(socket, buffer, len, flags);
}
ssize_t SHARED_EXPORT recvfrom(int socket, void *buffer, size_t len, int flags, struct sockaddr *addr, socklen_t *addrLen) {
static SyscallCheck<ssize_t, int, void *, size_t, int, struct sockaddr *, socklen_t *> prev("recvfrom");
return prev(socket, buffer, len, flags, addr, addrLen);
}
ssize_t SHARED_EXPORT recvmsg(int socket, struct msghdr *msg, int flags) {
static SyscallCheck<ssize_t, int, struct msghdr *, int> prev("recvmsg");
return prev(socket, msg, flags);
}
ssize_t SHARED_EXPORT send(int socket, const void *buf, size_t len, int flags) {
static SyscallCheck<ssize_t, int, const void *, size_t, int> prev("send");
return prev(socket, buf, len, flags);
}
ssize_t SHARED_EXPORT sendto(int socket, const void *msg, size_t len, int flags, const struct sockaddr *dest, socklen_t destLen) {
static SyscallCheck<ssize_t, int, const void *, size_t, int, const struct sockaddr *, socklen_t> prev("sendto");
return prev(socket, msg, len, flags, dest, destLen);
}
ssize_t SHARED_EXPORT sendmsg(int socket, const struct msghdr *msg, int flags) {
static SyscallCheck<ssize_t, int, const struct msghdr *, int> prev("sendmsg");
return prev(socket, msg, flags);
}
// Remaining: flock, fcntl(F_SETLKW), futex, sem_wait, sem_timedwait
#endif
|