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:
parent
56738d9383
commit
b7961bdb2f
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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")) {
|
||||||
|
Loading…
Reference in New Issue
Block a user