//
// aegis - project change supervisor
// Copyright (C) 2005-2008 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// .
//
#include
#include
#include
#include
#include
//
// This is a disgusting hack to get around a disgusting hack in glibc's
// implementation of sys/resource.h
//
// Glibc introduces a typedef for the first argument of getrlimit, and in
// some versions, fails to insulate this against C++ which has stricter
// enum to int rules than C does. This results in a compile time error.
//
#ifndef __USE_GNU
typedef int rlimit_resource_ty;
#else
typedef __rlimit_resource_t rlimit_resource_ty;
#endif
static void
adjust_resource(rlimit_resource_ty resource)
{
rlimit r;
if (getrlimit(resource, &r) >= 0 && r.rlim_cur != r.rlim_max)
{
r.rlim_cur = r.rlim_max;
setrlimit(resource, &r);
}
}
void
resource_limits_init()
{
//
// From getrlimit(2) manual page: "A child process created via
// fork(2) inherits its parents resource limits. Resource
// limits are preserved across execve(2)."
//
adjust_resource(RLIMIT_AS);
adjust_resource(RLIMIT_DATA);
adjust_resource(RLIMIT_FSIZE);
//
// Some operating systems generate the SIGXFSZ signal when a
// file exceeds the getrlimit(RLIMIT_FSIZE) size, in addition to
// returning the EFBIG errno value. By ignoring this signal, the
// error gets returned and it is possible to report the offending
// file's name, making for a more useful error message.
//
// Linux ignores this signal by default, but allows it to be
// set. Other posix implementations may not ignore this signal by
// default.
//
#ifdef SIGXFSZ
signal(SIGXFSZ, SIG_IGN);
#endif
}
#ifdef __linux__
static void
print_size(long size, const char *caption, int pagesize)
{
if (pagesize <= 1 || size == 0)
{
fprintf(stderr, "%8ld %s\n", size, caption);
return;
}
while (pagesize < 1024)
{
size = (size + 1) >> 1;
pagesize <<= 1;
}
pagesize >>= 10;
size *= pagesize;
if (size < 10000)
{
fprintf(stderr, "%4ldk %s\n", size, caption);
return;
}
size = (size + 512) >> 10;
if (size < 10000)
{
fprintf(stderr, "%4ldM %s\n", size, caption);
return;
}
size = (size + 512) >> 10;
fprintf(stderr, "%4ldG %s\n", size, caption);
}
#endif // __linux__
void
resource_usage_print()
{
#ifdef __linux__
const char *fn = "/proc/self/statm";
FILE *fp = fopen(fn, "r");
if (!fp)
return;
long size, resident, share, trs, drs, lrs;
fscanf(fp, "%ld%ld%ld%ld%ld%ld",
&size, &resident, &share, &trs, &drs, &lrs);
fclose(fp);
long pagesize = getpagesize();
print_size(size, "total program size", pagesize);
print_size(resident, "resident set size", pagesize);
print_size(share, "shared pages", pagesize);
print_size(trs, "text (code)", pagesize);
print_size(drs, "data/stack", pagesize);
print_size(lrs, "library", pagesize);
#endif // __linux__
}