libexplain
1.4.D001
|
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 : */