1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

Improve file descriptor leak detection to display likely culprit and filename.

This commit is contained in:
Alasdair Kergon 2008-08-01 19:51:27 +00:00
parent 56738d9383
commit b7961bdb2f
3 changed files with 74 additions and 13 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.40 - Version 2.02.40 -
================================ ================================
Improve file descriptor leak detection to display likely culprit and filename.
Change clustered mirror kernel module name from cmirror to dm-log-clustered. Change clustered mirror kernel module name from cmirror to dm-log-clustered.
Avoid looping forever in _pv_analyze_mda_raw used by pvck. Avoid looping forever in _pv_analyze_mda_raw used by pvck.
Change lvchange exit status to indicate if any part of the operation failed. Change lvchange exit status to indicate if any part of the operation failed.

View File

@ -24,6 +24,7 @@
/* Define some portable printing types */ /* Define some portable printing types */
#define PRIsize_t "zu" #define PRIsize_t "zu"
#define PRIptrdiff_t "td" #define PRIptrdiff_t "td"
#define PRIpid_t PRId32
struct str_list { struct str_list {
struct list list; struct list list;

View File

@ -1001,11 +1001,76 @@ static void _init_rand(void)
srand((unsigned) time(NULL) + (unsigned) getpid()); srand((unsigned) time(NULL) + (unsigned) getpid());
} }
static void _close_stray_fds(void) static const char *_get_cmdline(pid_t pid)
{
static char _proc_cmdline[32];
char buf[256];
int fd;
snprintf(buf, sizeof(buf), DEFAULT_PROC_DIR "/%u/cmdline", pid);
if ((fd = open(buf, O_RDONLY)) > 0) {
read(fd, _proc_cmdline, sizeof(_proc_cmdline) - 1);
_proc_cmdline[sizeof(_proc_cmdline) - 1] = '\0';
close(fd);
} else
_proc_cmdline[0] = '\0';
return _proc_cmdline;
}
static const char *_get_filename(int fd)
{
static char filename[PATH_MAX];
char buf[32]; /* Assumes short DEFAULT_PROC_DIR */
int size;
snprintf(buf, sizeof(buf), DEFAULT_PROC_DIR "/self/fd/%u", fd);
if ((size = readlink(buf, filename, sizeof(filename) - 1)) == -1)
filename[0] = '\0';
else
filename[size] = '\0';
return filename;
}
static void _close_descriptor(int fd, unsigned suppress_warnings,
const char *command, pid_t ppid,
const char *parent_cmdline)
{
int r;
const char *filename;
/* Ignore bad file descriptors */
if (fcntl(fd, F_GETFD) == -1 && errno == EBADF)
return;
if (!suppress_warnings)
filename = _get_filename(fd);
r = close(fd);
if (suppress_warnings)
return;
if (!r)
fprintf(stderr, "File descriptor %d (%s) leaked on "
"%s invocation.", fd, filename, command);
else if (errno == EBADF)
return;
else
fprintf(stderr, "Close failed on stray file descriptor "
"%d (%s): %s", fd, filename, strerror(errno));
fprintf(stderr, " Parent PID %" PRIpid_t ": %s\n", ppid, parent_cmdline);
}
static void _close_stray_fds(const char *command)
{ {
struct rlimit rlim; struct rlimit rlim;
int fd; int fd;
int suppress_warnings = 0; unsigned suppress_warnings = 0;
pid_t ppid = getppid();
const char *parent_cmdline = _get_cmdline(ppid);
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
fprintf(stderr, "getrlimit(RLIMIT_NOFILE) failed: %s\n", fprintf(stderr, "getrlimit(RLIMIT_NOFILE) failed: %s\n",
@ -1016,15 +1081,9 @@ static void _close_stray_fds(void)
if (getenv("LVM_SUPPRESS_FD_WARNINGS")) if (getenv("LVM_SUPPRESS_FD_WARNINGS"))
suppress_warnings = 1; suppress_warnings = 1;
for (fd = 3; fd < rlim.rlim_cur; fd++) { for (fd = 3; fd < rlim.rlim_cur; fd++)
if (suppress_warnings) _close_descriptor(fd, suppress_warnings, command, ppid,
close(fd); parent_cmdline);
else if (!close(fd))
fprintf(stderr, "File descriptor %d left open\n", fd);
else if (errno != EBADF)
fprintf(stderr, "Close failed on stray file "
"descriptor %d: %s\n", fd, strerror(errno));
}
} }
struct cmd_context *init_lvm(unsigned is_static) struct cmd_context *init_lvm(unsigned is_static)
@ -1162,13 +1221,13 @@ int lvm2_main(int argc, char **argv, unsigned is_static)
int ret, alias = 0; int ret, alias = 0;
struct cmd_context *cmd; struct cmd_context *cmd;
_close_stray_fds();
base = last_path_component(argv[0]); base = last_path_component(argv[0]);
if (strcmp(base, "lvm") && strcmp(base, "lvm.static") && if (strcmp(base, "lvm") && strcmp(base, "lvm.static") &&
strcmp(base, "initrd-lvm")) strcmp(base, "initrd-lvm"))
alias = 1; alias = 1;
_close_stray_fds(base);
if (is_static && strcmp(base, "lvm.static") && if (is_static && strcmp(base, "lvm.static") &&
path_exists(LVM_SHARED_PATH) && path_exists(LVM_SHARED_PATH) &&
!getenv("LVM_DID_EXEC")) { !getenv("LVM_DID_EXEC")) {