libexplain  1.4.D001
libexplain/buffer/enomem/rlimit_exceeded.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - a library of system-call-specific strerror replacements
00003  * Copyright (C) 2011, 2013, 2014 Peter Miller
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU Lesser General Public License as
00007  * published by the Free Software Foundation; either version 3 of the
00008  * License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include <libexplain/ac/sys/time.h>
00020 #include <libexplain/ac/sys/resource.h>
00021 
00022 #include <libexplain/buffer/enomem.h>
00023 #include <libexplain/buffer/gettext.h>
00024 #include <libexplain/buffer/long.h>
00025 #include <libexplain/buffer/rlimit.h>
00026 #include <libexplain/buffer/size_t.h>
00027 #include <libexplain/option.h>
00028 
00029 
00030 /*
00031  * return 0 if print nothing
00032  * return 1 if print anything
00033  */
00034 int
00035 explain_buffer_enomem_rlimit_exceeded(explain_string_buffer_t *sb, size_t size)
00036 {
00037     struct rlimit rlim;
00038     struct rusage ru;
00039 
00040     /*
00041      * The resource argument must be one of:
00042      *
00043      * RLIMIT_AS
00044      *     The maximum size of the process's virtual memory
00045      *     (address space) in bytes.  This limit affects calls to
00046      *     brk(2), mmap(2) and mremap(2), which fail with the error
00047      *     ENOMEM upon exceeding this limit.  Also automatic stack
00048      *     expansion will fail (and generate a SIGSEGV that kills
00049      *     the process if no alternate stack has been made available
00050      *     via sigaltstack(2)).  Since the value is a long, on
00051      *     machines with a 32-bit long ei
00052      *
00053      * RLIMIT_DATA
00054      *     The maximum size of the process's data segment (initialized
00055      *     data, uninitialized data, and heap).  This limit affects
00056      *     calls to brk(2) and sbrk(2), which fail with the error ENOMEM
00057      *     upon encountering the soft limit of this resource.  Compare
00058      *     with rusage::ru_idrsss (integral unshared data size)?!?
00059      */
00060     if (getrlimit(RLIMIT_AS, &rlim) <= 0)
00061         return 0;
00062     if (rlim.rlim_cur == RLIM_INFINITY)
00063     {
00064         explain_buffer_enomem_user(sb, rlim.rlim_cur);
00065         return 1;
00066     }
00067 
00068     if (getrusage(RUSAGE_SELF, &ru) < 0)
00069         return 0;
00070 
00071     /*  signed long  < rlim_t == unigned longs */
00072     if (ru.ru_maxrss < (long)rlim.rlim_cur)
00073         return 0;
00074 
00075     explain_buffer_gettext
00076     (
00077         sb,
00078         /*
00079          * xgettext:  This message is used to explain an
00080          * ENOMEM error reported by a system call (e.g.
00081          * mmap or shmat), in the case where the virtual
00082          * memory size of the process would have been
00083          * exceeded.  The relevant getrlimit values will be
00084          * printed separately.
00085          */
00086         i18n("the virtual memory size limit of the process "
00087             "would have been exceeded")
00088     );
00089 
00090     if (explain_option_dialect_specific())
00091     {
00092         explain_string_buffer_puts(sb, " (");
00093         explain_buffer_long(sb, ru.ru_maxrss);
00094         if (size == 0)
00095         {
00096             explain_string_buffer_puts(sb, " + ");
00097             explain_buffer_size_t(sb, size);
00098         }
00099         explain_string_buffer_puts(sb, " >= ");
00100         explain_buffer_rlim_t(sb, rlim.rlim_cur);
00101         explain_string_buffer_putc(sb, ')');
00102     }
00103 
00104     if (RLIM_INFINITY == rlim.rlim_max || ru.ru_maxrss < (long)rlim.rlim_max)
00105     {
00106         explain_string_buffer_puts(sb->footnotes, "; ");
00107         /* FIXME: i18n */
00108         explain_string_buffer_puts
00109         (
00110             sb->footnotes,
00111             /*
00112              * xgettext:  This supplemntary explanation is given when the user
00113              * can expand one of the limits to possdibly satisfy the memory
00114              * request.
00115              */
00116             i18n("you have some head room in the resource allocation, it may "
00117             "help to run the command " "\"ulimit -m hard\" and retry")
00118         );
00119     }
00120     return 1;
00121 }
00122 
00123 
00124 /* vim: set ts=8 sw=4 et : */