1cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//===-- FDInterposing.cpp ---------------------------------------*- C++ -*-===// 2cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 3cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// The LLVM Compiler Infrastructure 4cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 5cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// This file is distributed under the University of Illinois Open Source 6cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// License. See LICENSE.TXT for details. 7cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 8cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//===----------------------------------------------------------------------===// 9cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 10cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// This file helps with catching double close calls on unix integer file 11cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// descriptors by interposing functions for all file descriptor create and 12cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// close operations. A stack backtrace for every create and close function is 13cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// maintained, and every create and close operation is logged. When a double 14cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// file descriptor close is encountered, it will be logged. 15cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 16cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// To enable the interposing in a darwin program, set the DYLD_INSERT_LIBRARIES 17cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// environment variable as follows: 18cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// For sh: 19cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// DYLD_INSERT_LIBRARIES=/path/to/FDInterposing.dylib /path/to/executable 20cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// For tcsh: 21cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// (setenv DYLD_INSERT_LIBRARIES=/path/to/FDInterposing.dylib ; /path/to/executable) 22cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 23cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Other environment variables that can alter the default actions of this 24cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// interposing shared library include: 25cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 26cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// "FileDescriptorStackLoggingNoCompact" 27cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 28cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// With this environment variable set, all file descriptor create and 29cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// delete operations will be permanantly maintained in the event map. 30cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// The default action is to compact the create/delete events by removing 31cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// any previous file descriptor create events that are matched with a 32cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// corresponding file descriptor delete event when the next valid file 33cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// descriptor create event is detected. 34cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 35cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// "FileDescriptorMinimalLogging" 36cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 37cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// By default every file descriptor create and delete operation is logged 38cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// (to STDOUT by default, see the "FileDescriptorLogFile"). This can be 39cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// suppressed to only show errors and warnings by setting this environment 40cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// variable (the value in not important). 41cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 42cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// "FileDescriptorLogFile=<path>" 43cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 44cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// By default logging goes to STDOUT_FILENO, but this can be changed by 45cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// setting FileDescriptorLogFile. The value is a path to a file that 46cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// will be opened and used for logging. 47cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//===----------------------------------------------------------------------===// 48cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 49cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <assert.h> 50cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <dirent.h> 51cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <errno.h> 52cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <fcntl.h> 53cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <execinfo.h> 54cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <libgen.h> 55cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <mach-o/dyld.h> 56cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <mach-o/dyld-interposing.h> 57cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <stdlib.h> 58cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <stdio.h> 59cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <string.h> 60cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <sys/event.h> 61cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <sys/mman.h> 62cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <sys/socket.h> 63cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <sys/types.h> 64cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <sys/time.h> 651844426728e231df60ea88660e8fb112400f14c7Benjamin Kramer#include <tr1/memory> // for std::tr1::shared_ptr 66cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <unistd.h> 67cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <string> 68cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <vector> 69cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#include <map> 70cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 71cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 72cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton/// @def DISALLOW_COPY_AND_ASSIGN(TypeName) 73cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton/// Macro definition for easily disallowing copy constructor and 74cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton/// assignment operators in C++ classes. 75cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 76cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 77cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonTypeName(const TypeName&); \ 78cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonconst TypeName& operator=(const TypeName&) 79cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 80ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonextern "C" { 81ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton int accept$NOCANCEL (int, struct sockaddr * __restrict, socklen_t * __restrict); 82ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton int close$NOCANCEL(int); 83ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton int open$NOCANCEL(const char *, int, ...); 84ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton int __open_extended(const char *, int, uid_t, gid_t, int, struct kauth_filesec *); 85ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton} 86ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 87cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonnamespace fd_interposing { 88cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 89cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 90cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// String class so we can get formatted strings without having to worry 91cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// about the memory storage since it will allocate the memory it needs. 92cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 93cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclass String 94cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 95cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonpublic: 96cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton String () : 97cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_str (NULL) 98cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton {} 99cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 100cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton String (const char *format, ...) : 101cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_str (NULL) 102cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 103cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_list args; 104cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_start (args, format); 105cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton vprintf (format, args); 106cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_end (args); 107cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 108cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 109cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton ~String() 110cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 111cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton reset(); 112cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 113cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 114cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton void 115cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton reset (char *s = NULL) 116cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 117cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (m_str) 118cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton ::free (m_str); 119cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_str = s; 120cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 121cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 122cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton const char * 123cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton c_str () const 124cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 125cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton return m_str; 126cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 127cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 128cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton void 129cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton printf (const char *format, ...) 130cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 131cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_list args; 132cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_start (args, format); 133cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton vprintf (format, args); 134cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_end (args); 135cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 136cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton void 137cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton vprintf (const char *format, va_list args) 138cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 139cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton reset(); 140cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton ::vasprintf (&m_str, format, args); 141cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 142cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 143cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton void 144cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log (int log_fd) 145cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 146cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (m_str && log_fd >= 0) 147cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 148cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton const int len = strlen(m_str); 149cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (len > 0) 150cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 151cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton write (log_fd, m_str, len); 152cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton const char last_char = m_str[len-1]; 153cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (!(last_char == '\n' || last_char == '\r')) 154cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton write (log_fd, "\n", 1); 155cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 156cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 157cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 158cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonprotected: 159cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton char *m_str; 160cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 161cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonprivate: 162cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton DISALLOW_COPY_AND_ASSIGN (String); 163cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}; 164cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 165cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 166cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Type definitions 167cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 168cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef std::vector<void *> Frames; 169cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclass FDEvent; 170cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef std::vector<void *> Frames; 1711844426728e231df60ea88660e8fb112400f14c7Benjamin Kramertypedef std::tr1::shared_ptr<FDEvent> FDEventSP; 1721844426728e231df60ea88660e8fb112400f14c7Benjamin Kramertypedef std::tr1::shared_ptr<String> StringSP; 173cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 174cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 175cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 176cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// FDEvent 177cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 178cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// A class that describes a file desciptor event. 179cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 180cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// File descriptor events fall into one of two categories: create events 181cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// and delete events. 182cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 183cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclass FDEvent 184cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 185cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonpublic: 186cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton FDEvent (int fd, int err, const StringSP &string_sp, bool is_create, const Frames& frames) : 187cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_string_sp (string_sp), 188cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_frames (frames.begin(), frames.end()), 189cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_fd (fd), 190cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_err (err), 191cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_is_create (is_create) 192cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton {} 193cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 194cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton ~FDEvent () {} 195cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 196cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton bool 197cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton IsCreateEvent() const 198cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 199cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton return m_is_create; 200cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 201cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 202cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton bool 203cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton IsDeleteEvent() const 204cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 205cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton return !m_is_create; 206cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 207cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 208cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton Frames & 209cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton GetFrames () 210cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 211cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton return m_frames; 212cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 213cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 214cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton const Frames & 215cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton GetFrames () const 216cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 217cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton return m_frames; 218cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 219cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 220cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton int 221cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton GetFD () const 222cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 223cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton return m_fd; 224cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 225cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 226cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton int 227cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton GetError () const 228cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 229cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton return m_err; 230cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 231cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 232cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton void 233cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton Dump (int log_fd) const; 234cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 235cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton void 236cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton SetCreateEvent (FDEventSP &create_event_sp) 237cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 238cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_create_event_sp = create_event_sp; 239cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 240cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 241cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonprivate: 242cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // A shared pointer to a String that describes this event in 243cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // detail (all args and return and error values) 244cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton StringSP m_string_sp; 245cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // The frames for the stack backtrace for this event 246cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton Frames m_frames; 247cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // If this is a file descriptor delete event, this might contain 248cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // the correspoding file descriptor create event 249cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton FDEventSP m_create_event_sp; 250cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // The file descriptor for this event 251cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton int m_fd; 252cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // The error code (if any) for this event 253cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton int m_err; 254cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // True if this event is a file descriptor create event, false 255cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // if it is a file descriptor delete event 256cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton bool m_is_create; 257cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}; 258cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 259cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 260cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Templatized class that will save errno only if the "value" it is 261cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// constructed with is equal to INVALID. When the class goes out of 262cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// scope, it will restore errno if it was saved. 263cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 264cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontemplate <int INVALID> 265cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclass Errno 266cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 267cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonpublic: 268cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // Save errno only if we are supposed to 269cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton Errno (int value) : 270cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_saved_errno ((value == INVALID) ? errno : 0), 271cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_restore (value == INVALID) 272cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 273cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 274cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 275cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // Restore errno only if we are supposed to 276cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton ~Errno() 277cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 278cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (m_restore) 279cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton errno = m_saved_errno; 280cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 281cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 282cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // Accessor for the saved value of errno 283cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton int 284cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton get_errno() const 285cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 286cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton return m_saved_errno; 287cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 288cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 289cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonprotected: 290cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton const int m_saved_errno; 291cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton const bool m_restore; 292cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}; 293cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 294cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef Errno<-1> InvalidFDErrno; 295cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef Errno<-1> NegativeErrorErrno; 296cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef std::vector<FDEventSP> FDEventArray; 297cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytontypedef std::map<int, FDEventArray> FDEventMap; 298cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 299cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 300cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Globals 301cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 302cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Global event map that contains all file descriptor events. As file 303cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// descriptor create and close events come in, they will get filled 304cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// into this map (protected by g_mutex). When a file descriptor close 305cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// event is detected, the open event will be removed and placed into 306cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// the close event so if something tries to double close a file 307cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// descriptor we can show the previous close event and the file 308cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// desctiptor event that created it. When a new file descriptor create 309cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// event comes in, we will remove the previous one for that file 310cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// desctiptor unless the environment variable "FileDescriptorStackLoggingNoCompact" 311cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// is set. The file desctiptor history can be accessed using the 312cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// get_fd_history() function. 313cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic FDEventMap g_fd_event_map; 314cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// A mutex to protect access to our data structures in g_fd_event_map 315cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// and also our logging messages 316cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 317cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Log all file descriptor create and close events by default. Only log 318cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// warnings and erros if the "FileDescriptorMinimalLogging" environment 319cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// variable is set. 320cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic int g_log_all_calls = 1; 321cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// We compact the file descriptor events by default. Set the environment 322cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// varible "FileDescriptorStackLoggingNoCompact" to keep a full history. 323cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic int g_compact = 1; 324ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton// The current process ID 325ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic int g_pid = -1; 326ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic bool g_enabled = true; 327cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 328cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Mutex class that will lock a mutex when it is constructed, and unlock 329cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// it when is goes out of scope 330cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 331cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclass Locker 332cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 333cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonpublic: 334cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton Locker (pthread_mutex_t *mutex_ptr) : 335cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_mutex_ptr(mutex_ptr) 336cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 337cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton ::pthread_mutex_lock (m_mutex_ptr); 338cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 339cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 340cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // This allows clients to test try and acquire the mutex... 341cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton Locker (pthread_mutex_t *mutex_ptr, bool &lock_acquired) : 342cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_mutex_ptr(NULL) 343cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 344cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton lock_acquired = ::pthread_mutex_trylock(mutex_ptr) == 0; 345cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (lock_acquired) 346cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_mutex_ptr = mutex_ptr; 347cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 348cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 349cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton ~Locker () 350cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 351cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (m_mutex_ptr) 352cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton ::pthread_mutex_unlock (m_mutex_ptr); 353cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 354cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonprotected: 355cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton pthread_mutex_t *m_mutex_ptr; 356cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton}; 357cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 358cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic void 359cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog (const char *format, ...) __attribute__ ((format (printf, 1, 2))); 360cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 361cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic void 362cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog (int log_fd, const FDEvent *event, const char *format, ...) __attribute__ ((format (printf, 3, 4))); 363cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 364cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic void 365cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonbacktrace_log (const char *format, ...) __attribute__ ((format (printf, 1, 2))); 366cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 367cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic void 368ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonbacktrace_error (const char *format, ...) __attribute__ ((format (printf, 1, 2))); 369ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 370ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic void 371cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog_to_fd (int log_fd, const char *format, ...) __attribute__ ((format (printf, 2, 3))); 372cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 373cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic inline size_t 374cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonget_backtrace (Frames &frame_buffer, size_t frames_to_remove) 375cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 376cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton void *frames[2048]; 377cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton int count = ::backtrace (&frames[0], sizeof(frames)/sizeof(void*)); 378cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (count > frames_to_remove) 379cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton frame_buffer.assign (&frames[frames_to_remove], &frames[count]); 380cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton else 381cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton frame_buffer.assign (&frames[0], &frames[count]); 382cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton while (frame_buffer.back() < (void *)1024) 383cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton frame_buffer.pop_back(); 384cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton return frame_buffer.size(); 385cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 386cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 387ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic int g_log_fd = STDOUT_FILENO; 388ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic int g_initialized = 0; 389ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 390ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonconst char * 391ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonget_process_fullpath (bool force = false) 392ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton{ 393ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton static char g_process_fullpath[PATH_MAX] = {0}; 394ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (force || g_process_fullpath[0] == '\0') 395ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 396ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton // If DST is NULL, then return the number of bytes needed. 397ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton uint32_t len = sizeof(g_process_fullpath); 398ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (_NSGetExecutablePath (g_process_fullpath, &len) != 0) 399ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton strncpy (g_process_fullpath, "<error>", sizeof(g_process_fullpath)); 400ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 401ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return g_process_fullpath; 402ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton} 403ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 404ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton// Returns the current process ID, or -1 if inserposing not enabled for 405ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton// this process 406ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonstatic int 407ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonget_interposed_pid() 408ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton{ 409ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (!g_enabled) 410ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return -1; 411ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 412ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const pid_t pid = getpid(); 413ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_pid != pid) 414ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 415ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_pid == -1) 416ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 417ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton g_pid = pid; 418ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton log ("Interposing file descriptor create and delete functions for %s (pid=%i)\n", get_process_fullpath (true), pid); 419ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 420ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 421ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 422ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton log ("pid=%i: disabling interposing file descriptor create and delete functions for child process %s (pid=%i)\n", g_pid, get_process_fullpath (true), pid); 423ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton g_enabled = false; 424ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return -1; 425ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 426ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton // Log when our process changes 427ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 428ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return g_pid; 429ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton} 430ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 431cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonstatic int 432cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonget_logging_fd () 433cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 434ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (!g_enabled) 435ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return -1; 436cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 437ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (!g_initialized) 438cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 439ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton g_initialized = 1; 440cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 441ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const pid_t pid = get_interposed_pid(); 442cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 443ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_enabled) 444ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 445ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton // Keep all stack info around for all fd create and delete calls. 446ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton // Otherwise we will remove the fd create call when a corresponding 447ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton // fd delete call is received 448ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (getenv("FileDescriptorStackLoggingNoCompact")) 449ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton g_compact = 0; 450ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 451ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (getenv("FileDescriptorMinimalLogging")) 452ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton g_log_all_calls = 0; 453ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 454ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const char *log_path = getenv ("FileDescriptorLogFile"); 455ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (log_path) 456ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton g_log_fd = ::creat (log_path, 0660); 457ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 458ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton g_log_fd = STDOUT_FILENO; 459cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 460ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton // Only let this interposing happen on the first time this matches 461ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton // and stop this from happening so any child processes don't also 462ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton // log their file descriptors 463ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton ::unsetenv ("DYLD_INSERT_LIBRARIES"); 464ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 465ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 466cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 467ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton log ("pid=%i: logging disabled\n", getpid()); 468cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 469cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 470cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton return g_log_fd; 471cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 472cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 473cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid 474cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog_to_fd (int log_fd, const char *format, va_list args) 475cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 476cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (format && format[0] && log_fd >= 0) 477cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 478cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton char buffer[PATH_MAX]; 479cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton const int count = ::vsnprintf (buffer, sizeof(buffer), format, args); 480cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (count > 0) 481cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton write (log_fd, buffer, count); 482cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 483cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 484cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 485cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid 486cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog_to_fd (int log_fd, const char *format, ...) 487cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 488cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (format && format[0]) 489cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 490cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_list args; 491cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_start (args, format); 492cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log_to_fd (log_fd, format, args); 493cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_end (args); 494cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 495cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 496cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 497cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid 498cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog (const char *format, va_list args) 499cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 500cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log_to_fd (get_logging_fd (), format, args); 501cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 502cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 503cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid 504cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog (const char *format, ...) 505cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 506cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (format && format[0]) 507cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 508cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_list args; 509cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_start (args, format); 510cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log (format, args); 511cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_end (args); 512cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 513cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 514cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 515cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid 516cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonlog (int log_fd, const FDEvent *event, const char *format, ...) 517cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 518cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (format && format[0]) 519cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 520cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_list args; 521cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_start (args, format); 522cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log_to_fd (log_fd, format, args); 523cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_end (args); 524cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 525cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (event) 526cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton event->Dump(log_fd); 527cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 528cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 529cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid 530cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonFDEvent::Dump (int log_fd) const 531cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 532cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (log_fd >= 0) 533cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 534cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log_to_fd (log_fd, "%s\n", m_string_sp->c_str()); 535cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (!m_frames.empty()) 536cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton ::backtrace_symbols_fd (m_frames.data(), m_frames.size(), log_fd); 537cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 538cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (m_create_event_sp) 539cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 540cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log_to_fd (log_fd, "\nfd=%i was created with this event:\n", m_fd); 541cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton m_create_event_sp->Dump (log_fd); 542cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log_to_fd (log_fd, "\n"); 543cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 544cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 545cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 546cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 547cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 548cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid 549cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonbacktrace_log (const char *format, ...) 550cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 551cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton const int log_fd = get_logging_fd (); 552cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (log_fd >= 0) 553cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 554cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (format && format[0]) 555cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 556cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_list args; 557cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_start (args, format); 558cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log (format, args); 559cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton va_end (args); 560cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 561cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 562cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton Frames frames; 56306a305818fe09fa662ed09268a82b077e22f800fGreg Clayton if (get_backtrace(frames, 2)) 564cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton ::backtrace_symbols_fd (frames.data(), frames.size(), log_fd); 565cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 566cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 567cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 568cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 569cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid 570ad639b6fa8faa3833585498a1612f605a7302961Greg Claytonbacktrace_error (const char *format, ...) 571ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton{ 572ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 573ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 574ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 575ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int log_fd = get_logging_fd (); 576ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (log_fd >= 0) 577ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 578ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton log ("\nerror: %s (pid=%i): ", get_process_fullpath (), pid); 579ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 580ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (format && format[0]) 581ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 582ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton va_list args; 583ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton va_start (args, format); 584ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton log (format, args); 585ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton va_end (args); 586ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 587ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 588ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Frames frames; 589ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (get_backtrace(frames, 2)) 590ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton ::backtrace_symbols_fd (frames.data(), frames.size(), log_fd); 591ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 592ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 593ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton} 594cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 595cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonvoid 596cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonsave_backtrace (int fd, int err, const StringSP &string_sp, bool is_create) 597cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 598cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton Frames frames; 599cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton get_backtrace(frames, 2); 600cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 601cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton FDEventSP fd_event_sp (new FDEvent (fd, err, string_sp, is_create, frames)); 602cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 603cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton FDEventMap::iterator pos = g_fd_event_map.find (fd); 604cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 605cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (pos != g_fd_event_map.end()) 606cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 607cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // We have history for this fd... 608cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 609cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton FDEventArray &event_array = g_fd_event_map[fd]; 610cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (fd_event_sp->IsCreateEvent()) 611cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 612cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // The current fd event is a function that creates 613cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // a descriptor, check in case last event was 614cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // a create event. 615cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (event_array.back()->IsCreateEvent()) 616cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 617cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton const int log_fd = get_logging_fd(); 618cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // Two fd create functions in a row, we missed 619cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // a function that closes a fd... 620cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log (log_fd, fd_event_sp.get(), "\nwarning: unmatched file descriptor create event fd=%i (we missed a file descriptor close event):\n", fd); 621cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 622cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton else if (g_compact) 623cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 624cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // We are compacting so we remove previous create event 625cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // when we get the correspinding delete event 626cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton event_array.pop_back(); 627cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 628cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 629cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton else 630cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 631cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // The current fd event is a function that deletes 632cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // a descriptor, check in case last event for this 633cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // fd was a delete event (double close!) 634cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (event_array.back()->IsDeleteEvent()) 635cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 636cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton const int log_fd = get_logging_fd(); 637cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // Two fd delete functions in a row, we must 638cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // have missed some function that opened a descriptor 639cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log (log_fd, fd_event_sp.get(), "\nwarning: unmatched file descriptor close event for fd=%d (we missed the file descriptor create event):\n", fd); 640cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 641cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton else if (g_compact) 642cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 643cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // Since this is a close event, we want to remember the open event 644cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // that this close if for... 645cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton fd_event_sp->SetCreateEvent(event_array.back()); 646cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // We are compacting so we remove previous create event 647cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // when we get the correspinding delete event 648cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton event_array.pop_back(); 649cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 650cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 651cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 652cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton event_array.push_back(fd_event_sp); 653cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 654cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton else 655cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 656cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton g_fd_event_map[fd].push_back(fd_event_sp); 657cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 658cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 659cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 660cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 661cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// socket() interpose function 662cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 663cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 664cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonsocket$__interposed__ (int domain, int type, int protocol) 665cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 666ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 667ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 668ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 669ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 670ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int fd = ::socket (domain, type, protocol); 671ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton InvalidFDErrno fd_errno(fd); 672ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String); 673ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd == -1) 674ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->printf("pid=%i: socket (domain = %i, type = %i, protocol = %i) => fd=%i errno = %i", pid, domain, type, protocol, fd, fd_errno.get_errno()); 675ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 676ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->printf("pid=%i: socket (domain = %i, type = %i, protocol = %i) => fd=%i", pid, domain, type, protocol, fd); 677ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 678ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 679ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 680ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, fd_errno.get_errno(), description_sp, true); 681ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return fd; 682ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 683cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton else 684ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 685ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return ::socket (domain, type, protocol); 686ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 687cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 688cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 689cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 690cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// socketpair() interpose function 691cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 692cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 693cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonsocketpair$__interposed__ (int domain, int type, int protocol, int fds[2]) 694cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 695ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 696ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 697ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 698ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 699ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton fds[0] = -1; 700ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton fds[1] = -1; 701ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int err = socketpair (domain, type, protocol, fds); 702ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton NegativeErrorErrno err_errno(err); 703ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String ("pid=%i: socketpair (domain=%i, type=%i, protocol=%i, {fd=%i, fd=%i}) -> err=%i", pid, domain, type, protocol, fds[0], fds[1], err)); 704ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 705ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 706ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fds[0] >= 0) 707ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fds[0], err_errno.get_errno(), description_sp, true); 708ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fds[1] >= 0) 709ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fds[1], err_errno.get_errno(), description_sp, true); 710ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return err; 711ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 712ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 713ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 714ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return socketpair (domain, type, protocol, fds); 715ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 716cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 717cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 718cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 719cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// open() interpose function 720cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 721cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 722cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonopen$__interposed__ (const char *path, int oflag, int mode) 723cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 724ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 725ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 726cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 727ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 728ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton int fd = -2; 729ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String); 730ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (oflag & O_CREAT) 731ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 732ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton fd = ::open (path, oflag, mode); 733ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->printf("pid=%i: open (path = '%s', oflag = %i, mode = %i) -> fd=%i", pid, path, oflag, mode, fd); 734ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 735ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 736ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 737ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton fd = ::open (path, oflag); 738ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->printf("pid=%i: open (path = '%s', oflag = %i) -> fd=%i", pid, path, oflag, fd); 739ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 740ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 741ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton InvalidFDErrno fd_errno(fd); 742ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 743ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 744ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 745ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, fd_errno.get_errno(), description_sp, true); 746ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return fd; 747cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 748cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton else 749cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 750ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return ::open (path, oflag, mode); 751cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 752cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 753cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 754cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 755cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// open$NOCANCEL() interpose function 756cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 757cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 758cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonopen$NOCANCEL$__interposed__ (const char *path, int oflag, int mode) 759cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 760ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 761ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 762ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 763ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 764ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int fd = ::open$NOCANCEL (path, oflag, mode); 765ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton InvalidFDErrno fd_errno(fd); 766ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String ("pid=%i: open$NOCANCEL (path = '%s', oflag = %i, mode = %i) -> fd=%i", pid, path, oflag, mode, fd)); 767ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 768ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 769ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 770ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, fd_errno.get_errno(), description_sp, true); 771ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return fd; 772ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 773ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 774ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 775ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return ::open$NOCANCEL (path, oflag, mode); 776ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 777cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 778cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 779cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 780cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 781cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// __open_extended() interpose function 782cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 783cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 784cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton__open_extended$__interposed__ (const char *path, int oflag, uid_t uid, gid_t gid, int mode, struct kauth_filesec *fsacl) 785cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 786ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 787ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 788ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 789ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 790ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int fd = ::__open_extended (path, oflag, uid, gid, mode, fsacl); 791ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton InvalidFDErrno fd_errno(fd); 792ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String ("pid=%i: __open_extended (path='%s', oflag=%i, uid=%i, gid=%i, mode=%i, fsacl=%p) -> fd=%i", pid, path, oflag, uid, gid, mode, fsacl, fd)); 793ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 794ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 795ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 796ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, fd_errno.get_errno(), description_sp, true); 797ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return fd; 798ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 799ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 800ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 801ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return ::__open_extended (path, oflag, uid, gid, mode, fsacl); 802ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 803cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 804cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 805cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 806cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// kqueue() interpose function 807cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 808cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 809cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonkqueue$__interposed__ (void) 810cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 811ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 812ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 813ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 814ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 815ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int fd = ::kqueue (); 816ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton InvalidFDErrno fd_errno(fd); 817ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String ("pid=%i: kqueue () -> fd=%i", pid, fd)); 818ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 819ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 820ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 821ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, fd_errno.get_errno(), description_sp, true); 822ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return fd; 823ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 824ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 825ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 826ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return ::kqueue (); 827ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 828cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 829cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 830cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 831cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// shm_open() interpose function 832cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 833cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 834cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonshm_open$__interposed__ (const char *path, int oflag, int mode) 835cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 836ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 837ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 838ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 839ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 840ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int fd = ::shm_open (path, oflag, mode); 841ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton InvalidFDErrno fd_errno(fd); 842ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String ("pid=%i: shm_open (path = '%s', oflag = %i, mode = %i) -> fd=%i", pid, path, oflag, mode, fd)); 843ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 844ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 845ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 846ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, fd_errno.get_errno(), description_sp, true); 847ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return fd; 848ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 849ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 850ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 851ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return ::shm_open (path, oflag, mode); 852ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 853cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 854cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 855cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 856cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// accept() interpose function 857cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 858cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 859cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonaccept$__interposed__ (int socket, struct sockaddr *address, socklen_t *address_len) 860cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 861ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 862ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 863ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 864ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 865ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int fd = ::accept (socket, address, address_len); 866ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton InvalidFDErrno fd_errno(fd); 867ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String ("pid=%i: accept (socket=%i, ...) -> fd=%i", pid, socket, fd)); 868ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 869ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 870ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 871ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, fd_errno.get_errno(), description_sp, true); 872ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return fd; 873ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 874ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 875ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 876ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return ::accept (socket, address, address_len); 877ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 878cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 879cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 880cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 881cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 882cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// accept$NOCANCEL() interpose function 883cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 884cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 885cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonaccept$NOCANCEL$__interposed__ (int socket, struct sockaddr *address, socklen_t *address_len) 886cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 887ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 888ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 889ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 890ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 891ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int fd = ::accept$NOCANCEL (socket, address, address_len); 892ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton InvalidFDErrno fd_errno(fd); 893ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String ("pid=%i: accept$NOCANCEL (socket=%i, ...) -> fd=%i", pid, socket, fd)); 894ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 895ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 896ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 897ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, fd_errno.get_errno(), description_sp, true); 898ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return fd; 899ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 900ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 901ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 902ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return ::accept$NOCANCEL (socket, address, address_len); 903ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 904cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 905cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 906cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 907cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// dup() interpose function 908cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 909cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 910cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytondup$__interposed__ (int fd2) 911cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 912ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 913ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 914ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 915ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 916ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int fd = ::dup (fd2); 917ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton InvalidFDErrno fd_errno(fd); 918ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String ("pid=%i: dup (fd2=%i) -> fd=%i", pid, fd2, fd)); 919ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 920ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 921ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 922ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, fd_errno.get_errno(), description_sp, true); 923ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return fd; 924ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 925ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 926ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 927ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return ::dup (fd2); 928ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 929cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 930cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 931cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 932cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// dup2() interpose function 933cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 934cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 935cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytondup2$__interposed__ (int fd1, int fd2) 936cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 937ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 938ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 939ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 940ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 941ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton // If "fd2" is already opened, it will be closed during the 942ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton // dup2 call below, so we need to see if we have fd2 in our 943ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton // open map and treat it as a close(fd2) 944ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton FDEventMap::iterator pos = g_fd_event_map.find (fd2); 945ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP dup2_close_description_sp(new String ("pid=%i: dup2 (fd1=%i, fd2=%i) -> will close (fd=%i)", pid, fd1, fd2, fd2)); 946ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pos != g_fd_event_map.end() && pos->second.back()->IsCreateEvent()) 947ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd2, 0, dup2_close_description_sp, false); 948ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 949ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int fd = ::dup2(fd1, fd2); 950ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton InvalidFDErrno fd_errno(fd); 951ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String ("pid=%i: dup2 (fd1=%i, fd2=%i) -> fd=%i", pid, fd1, fd2, fd)); 952ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 953ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 954ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 955ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 956ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, fd_errno.get_errno(), description_sp, true); 957ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return fd; 958ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 959ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 960ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 961ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return ::dup2(fd1, fd2); 962ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 963cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 964cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 965cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 966cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// close() interpose function 967cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 968cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 969cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclose$__interposed__ (int fd) 970cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 971ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 972ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 973cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 974ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 975ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int err = close(fd); 976ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton NegativeErrorErrno err_errno(err); 977ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp (new String); 978ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (err == -1) 979ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->printf("pid=%i: close (fd=%i) => %i errno = %i (%s))", pid, fd, err, err_errno.get_errno(), strerror(err_errno.get_errno())); 980ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 981ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->printf("pid=%i: close (fd=%i) => %i", pid, fd, err); 982ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 983ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 984cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 985ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (err == 0) 986ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 987ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 988ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, err, description_sp, false); 989ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 990ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else if (err == -1) 991ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 992ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (err_errno.get_errno() == EBADF && fd != -1) 993cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 994ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton backtrace_error ("close (fd=%d) resulted in EBADF:\n", fd); 995ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 996ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton FDEventMap::iterator pos = g_fd_event_map.find (fd); 997ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pos != g_fd_event_map.end()) 998ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 999ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton log (get_logging_fd(), pos->second.back().get(), "\nfd=%d was previously %s with this event:\n", fd, pos->second.back()->IsCreateEvent() ? "opened" : "closed"); 1000ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 1001cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 1002cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 1003ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return err; 1004ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 1005ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 1006ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 1007ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return close (fd); 1008cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 1009cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 1010cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 1011cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 1012cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// close$NOCANCEL() interpose function 1013cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 1014cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 1015cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonclose$NOCANCEL$__interposed__ (int fd) 1016cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 1017ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 1018ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 1019cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 1020ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 1021ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int err = close$NOCANCEL(fd); 1022ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton NegativeErrorErrno err_errno(err); 1023ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp (new String); 1024ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (err == -1) 1025ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->printf("pid=%i: close$NOCANCEL (fd=%i) => %i errno = %i (%s))", pid, fd, err, err_errno.get_errno(), strerror(err_errno.get_errno())); 1026ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 1027ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->printf("pid=%i: close$NOCANCEL (fd=%i) => %i", pid, fd, err); 1028ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 1029ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 1030ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 1031ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (err == 0) 1032cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 1033ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fd >= 0) 1034ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fd, err, description_sp, false); 1035ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 1036ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else if (err == -1) 1037ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 1038ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (err_errno.get_errno() == EBADF && fd != -1) 1039cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 1040ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton backtrace_error ("close$NOCANCEL (fd=%d) resulted in EBADF\n:", fd); 1041ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton 1042ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton FDEventMap::iterator pos = g_fd_event_map.find (fd); 1043ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pos != g_fd_event_map.end()) 1044ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 1045ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton log (get_logging_fd(), pos->second.back().get(), "\nfd=%d was previously %s with this event:\n", fd, pos->second.back()->IsCreateEvent() ? "opened" : "closed"); 1046ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 1047cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 1048cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 1049ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return err; 1050cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 1051ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 1052ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 1053ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return close$NOCANCEL(fd); 1054ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 1055cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 1056cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 1057cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 1058cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// pipe() interpose function 1059cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 1060cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" int 1061cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonpipe$__interposed__ (int fds[2]) 1062cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 1063ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int pid = get_interposed_pid(); 1064ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (pid >= 0) 1065ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 1066ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton Locker locker (&g_mutex); 1067ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton fds[0] = -1; 1068ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton fds[1] = -1; 1069ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int err = pipe (fds); 1070ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton const int saved_errno = errno; 1071ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton StringSP description_sp(new String ("pid=%i: pipe ({fd=%i, fd=%i}) -> err=%i", pid, fds[0], fds[1], err)); 1072ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (g_log_all_calls) 1073ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton description_sp->log (get_logging_fd()); 1074ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fds[0] >= 0) 1075ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fds[0], saved_errno, description_sp, true); 1076ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton if (fds[1] >= 0) 1077ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton save_backtrace (fds[1], saved_errno, description_sp, true); 1078ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton errno = saved_errno; 1079ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return err; 1080ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 1081ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton else 1082ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton { 1083ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton return pipe (fds); 1084ad639b6fa8faa3833585498a1612f605a7302961Greg Clayton } 1085cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 1086cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 1087cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 1088cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// get_fd_history() 1089cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 1090cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// This function allows runtime access to the file descriptor history. 1091cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 1092cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// @param[in] log_fd 1093cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// The file descriptor to log to 1094cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// 1095cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// @param[in] fd 1096cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// The file descriptor whose history should be dumped 1097cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 1098cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonextern "C" void 1099cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Claytonget_fd_history (int log_fd, int fd) 1100cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton{ 1101cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton // "create" below needs to be outside of the mutex locker scope 1102cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (log_fd >= 0) 1103cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 1104cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton bool got_lock = false; 1105cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton Locker locker (&g_mutex, got_lock); 1106cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (got_lock) 1107cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 1108cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton FDEventMap::iterator pos = g_fd_event_map.find (fd); 1109cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log_to_fd (log_fd, "Dumping file descriptor history for fd=%i:\n", fd); 1110cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton if (pos != g_fd_event_map.end()) 1111cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 1112cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton FDEventArray &event_array = g_fd_event_map[fd]; 1113cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton const size_t num_events = event_array.size(); 1114cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton for (size_t i=0; i<num_events; ++i) 1115cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton event_array[i]->Dump (log_fd); 1116cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 1117cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton else 1118cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 1119cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log_to_fd (log_fd, "error: no file descriptor events found for fd=%i\n", fd); 1120cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 1121cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 1122cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton else 1123cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton { 1124cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton log_to_fd (log_fd, "error: fd event mutex is locked...\n"); 1125cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 1126cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton } 1127cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} 1128cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 1129cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 1130cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// Interposing 1131cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton//---------------------------------------------------------------------- 1132cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// FD creation routines 1133cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(accept$__interposed__, accept); 1134cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(accept$NOCANCEL$__interposed__, accept$NOCANCEL); 1135cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(dup$__interposed__, dup); 1136cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(dup2$__interposed__, dup2); 1137cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(kqueue$__interposed__, kqueue); 1138cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(open$__interposed__, open); 1139cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(open$NOCANCEL$__interposed__, open$NOCANCEL); 1140cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(__open_extended$__interposed__, __open_extended); 1141cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(pipe$__interposed__, pipe); 1142cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(shm_open$__interposed__, shm_open); 1143cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(socket$__interposed__, socket); 1144cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(socketpair$__interposed__, socketpair); 1145cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 1146cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton// FD deleting routines 1147cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(close$__interposed__, close); 1148cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg ClaytonDYLD_INTERPOSE(close$NOCANCEL$__interposed__, close$NOCANCEL); 1149cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 1150cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton} // namespace fd_interposing 1151cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 1152cb5ad0be065d99d933fc8e3a2526c222b3c0a004Greg Clayton 1153