libexplain  1.4.D001
libexplain/buffer/errno/fork.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2008, 2009, 2013 Peter Miller
00004  *
00005  * This program is free software; you can redistribute it and/or modify it
00006  * under the terms of the GNU Lesser General Public License as published by
00007  * the Free Software Foundation; either version 3 of the License, or (at
00008  * 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/errno.h>
00020 
00021 #include <libexplain/buffer/enomem.h>
00022 #include <libexplain/buffer/errno/fork.h>
00023 #include <libexplain/buffer/errno/generic.h>
00024 #include <libexplain/buffer/gettext.h>
00025 #include <libexplain/explanation.h>
00026 #include <libexplain/option.h>
00027 
00028 
00029 static void
00030 explain_buffer_errno_fork_system_call(explain_string_buffer_t *sb,
00031     int errnum)
00032 {
00033     (void)errnum;
00034     explain_string_buffer_puts(sb, "fork()");
00035 }
00036 
00037 
00038 void
00039 explain_buffer_errno_fork_explanation(explain_string_buffer_t *sb,
00040     int errnum, const char *syscall_name)
00041 {
00042     /*
00043      * http://www.opengroup.org/onlinepubs/009695399/functions/fork.html
00044      */
00045     switch (errnum)
00046     {
00047     case EAGAIN:
00048         explain_buffer_gettext
00049         (
00050             sb,
00051             /*
00052              * xgettext: This message is used to explain fork(2) errors,
00053              * when no more specific cause can be determined.
00054              */
00055             i18n("the system lacked the necessary resources to create "
00056             "another process; or, the system-imposed limit on the total "
00057             "number of processes under execution system-wide would be "
00058             "exceeded; or, the system-imposed limit on the total number "
00059             "of processes under execution by a single user {CHILD_MAX} "
00060             "would be exceeded")
00061         );
00062 
00063         /*
00064          *  FIXME: distinguish the 4 cases
00065          *
00066          *  sysconf(_SC_CHILD_MAX)
00067          *      The max number of simultaneous processes per user ID.  Must
00068          *      not be less than _POSIX_CHILD_MAX (25).
00069          *
00070          *  getrlimit(RLIMIT_NPROC)
00071          *      The maximum number of processes (or, more precisely on
00072          *      Linux, threads) that can be created for the real user ID of
00073          *      the calling process.  Upon encountering this limit, fork(2)
00074          *      fails with the error EAGAIN.
00075          */
00076 #ifdef HAVE_SYS_CAPABILITY_H
00077         if (explain_option_dialect_specific())
00078         {
00079             explain_string_buffer_puts(sb, ", ");
00080             explain_buffer_gettext
00081             (
00082                 sb,
00083                 /*
00084                  * xgettext: This message is used when explaining
00085                  * the capabilities required to exceed system limits
00086                  * on the number of processes a user may execute
00087                  * simultaniously.
00088                  */
00089                 i18n("to exceed the limit on the number of processes, "
00090                 "the process must have either the CAP_SYS_ADMIN or the "
00091                 "CAP_SYS_RESOURCE capability")
00092             );
00093         }
00094 #endif
00095         break;
00096 
00097     case ENOMEM:
00098         /*
00099          * The Open Group Base Specifications Issue 6
00100          * IEEE Std 1003.1, 2004 Edition
00101          *
00102          * fork() Rationale states
00103          *    "The [ENOMEM] error value is reserved for those
00104          *    implementations that detect and distinguish such a
00105          *    condition. This condition occurs when an implementation
00106          *    detects that there is not enough memory to create the
00107          *    process. This is intended to be returned when [EAGAIN] is
00108          *    inappropriate because there can never be enough memory
00109          *    (either primary or secondary storage) to perform the
00110          *    operation. Since fork() duplicates an existing process,
00111          *    this must be a condition where there is sufficient memory
00112          *    for one such process, but not for two. Many historical
00113          *    implementations actually return [ENOMEM] due to temporary
00114          *    lack of memory, a case that is not generally distinct from
00115          *    [EAGAIN] from the perspective of a conforming application.
00116          *
00117          *    "Part of the reason for including the optional error
00118          *    [ENOMEM] is because the SVID specifies it and it should
00119          *    be reserved for the error condition specified there. The
00120          *    condition is not applicable on many implementations."
00121          */
00122         explain_buffer_enomem_kernel(sb);
00123         break;
00124 
00125     default:
00126         explain_buffer_errno_generic(sb, errnum, syscall_name);
00127         break;
00128     }
00129 }
00130 
00131 
00132 void
00133 explain_buffer_errno_fork(explain_string_buffer_t *sb, int errnum)
00134 {
00135     explain_explanation_t exp;
00136 
00137     explain_explanation_init(&exp, errnum);
00138     explain_buffer_errno_fork_system_call(&exp.system_call_sb, errnum);
00139     explain_buffer_errno_fork_explanation(&exp.explanation_sb, errnum, "fork");
00140     explain_explanation_assemble(&exp, sb);
00141 }
00142 
00143 
00144 /* vim: set ts=8 sw=4 et : */