root/software/fss-parallel-tools/fdleak.c @ 65b83771
| 7e8045d8 | David Sorber | /**
|
|
* Copyright © 2019, Oracle and/or its affiliates. All rights reserved.
|
|||
*
|
|||
* Licensed under the Universal Permissive License v 1.0 as shown at
|
|||
* http://oss.oracle.com/licenses/upl
|
|||
*
|
|||
*/
|
|||
#include "fdleak.h"
|
|||
#include <fcntl.h>
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
#include <sys/resource.h> // for getrlimit, rlimit, RLIMIT_NO...
|
|||
// File descriptor leak check
|
|||
static size_t n_open_fds_at_start = 0;
|
|||
enum { OFAS_SIZE = 100 };
|
|||
enum { CHECK_FD_LIMIT = 1024 };
|
|||
static int open_fds_at_start[OFAS_SIZE];
|
|||
static int fd_is_open(int fd) {
|
|||
// Use fcntl F_GETFL to figure out if file is open
|
|||
return fcntl(fd, F_GETFL) != -1;
|
|||
}
|
|||
void find_open_fds_at_start(void) {
|
|||
struct rlimit rlim;
|
|||
if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
|
|||
fprintf(stderr, "FATAL: getrlimit() failed\n");
|
|||
abort();
|
|||
}
|
|||
for (int fd = 0; fd < (int)rlim.rlim_cur && fd < CHECK_FD_LIMIT; ++fd) {
|
|||
if (fd_is_open(fd)) {
|
|||
if (n_open_fds_at_start < OFAS_SIZE) {
|
|||
open_fds_at_start[n_open_fds_at_start++] = fd;
|
|||
} else {
|
|||
fprintf(stderr, "FATAL: too many open_fds_at_start %zd\n",
|
|||
n_open_fds_at_start);
|
|||
abort();
|
|||
}
|
|||
}
|
|||
}
|
|||
}
|
|||
static int fd_was_open(int fd) {
|
|||
for (size_t i = 0; i < n_open_fds_at_start; ++i) {
|
|||
if (fd == open_fds_at_start[i]) {
|
|||
return !!1;
|
|||
}
|
|||
}
|
|||
return !!0;
|
|||
}
|
|||
void fdleak_check(void)
|
|||
{
|
|||
struct rlimit rlim;
|
|||
if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
|
|||
fprintf(stderr, "FATAL: getrlimit() failed\n");
|
|||
abort();
|
|||
}
|
|||
for (int fd = 0; fd < (int)rlim.rlim_cur && fd < CHECK_FD_LIMIT; ++fd) {
|
|||
if (!fd_was_open(fd) && fd_is_open(fd)) {
|
|||
fprintf(stderr, "BUG: fd %d still open at end of program\n", fd);
|
|||
}
|
|||
}
|
|||
}
|