Project

General

Profile

Download (1.8 KB) Statistics
| Branch: | Tag: | Revision:
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);
}
}
}