[SV 13651] Handle out-of-memory conditions slightly more gracefully.

* makeint.h: Change OUT_OF_MEM() macro to out_of_memory() function.
* output.h, job.h: Move FD_* macros from job.h to output.h.
* output.c (output_write): Write a buffer to an FD directly.
(out_of_memory): Use output_write() to avoid allocating more
memory while writing the error, and call exit() instead of die().
This does mean we can't translate the error string, though.
* misc.c (xmalloc, xcalloc, xrealloc, xstrdup, xstrndup): Call new
out_of_memory() rather than OUT_OF_MEM().
* read.c (parse_file_seq): Ditto.
This commit is contained in:
Paul Smith 2017-01-02 15:46:30 -05:00
parent 2b8e3bb23f
commit 68be4f74fc
10 changed files with 61 additions and 22 deletions

View File

@ -375,6 +375,8 @@ struct ar_hdr
#ifndef AR_HDR_SIZE
# define AR_HDR_SIZE (sizeof (struct ar_hdr))
#endif
#include "output.h"
/* Takes three arguments ARCHIVE, FUNCTION and ARG.
@ -891,7 +893,7 @@ ar_member_touch (const char *arname, const char *memname)
EINTRLOOP (o, lseek (fd, pos, 0));
if (o < 0)
goto lose;
EINTRLOOP (r, write (fd, &ar_hdr, AR_HDR_SIZE));
r = output_write (fd, &ar_hdr, AR_HDR_SIZE);
if (r != AR_HDR_SIZE)
goto lose;
/* The file's mtime is the time we we want. */
@ -913,7 +915,7 @@ ar_member_touch (const char *arname, const char *memname)
EINTRLOOP (o, lseek (fd, pos, 0));
if (o < 0)
goto lose;
EINTRLOOP (r, write (fd, &ar_hdr, AR_HDR_SIZE));
r = output_write (fd, &ar_hdr, AR_HDR_SIZE);
if (r != AR_HDR_SIZE)
goto lose;
close (fd);

View File

@ -335,3 +335,6 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
/* Build host information. */
#define MAKE_HOST "Amiga"
/* Define to `int' if <sys/types.h> does not define. */
#define ssize_t int

View File

@ -484,6 +484,9 @@ char *ttyname (int);
#endif
#endif
/* Define to `int' if <sys/types.h> does not define. */
#define ssize_t int
/* Define to 'int' if <sys/types.h> doesn't define. */
#define uid_t int

View File

@ -111,3 +111,6 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
/* Grok DOS paths (drive specs and backslash path element separators) */
#define HAVE_DOS_PATHS
/* Define to `int' if <sys/types.h> does not define. */
#define ssize_t int

3
job.h
View File

@ -62,9 +62,6 @@ char **construct_command_argv (char *line, char **restp, struct file *file,
#ifdef VMS
int child_execute_job (struct child *child, char *argv);
#else
# define FD_STDIN (fileno (stdin))
# define FD_STDOUT (fileno (stdout))
# define FD_STDERR (fileno (stderr))
int child_execute_job (struct output *out, int good_stdin, char **argv, char **envp);
#endif

View File

@ -484,6 +484,7 @@ void error (const floc *flocp, size_t length, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
void fatal (const floc *flocp, size_t length, const char *fmt, ...)
__attribute__ ((noreturn, __format__ (__printf__, 3, 4)));
void out_of_memory () __attribute__((noreturn));
/* When adding macros to this list be sure to update the value of
XGETTEXT_OPTIONS in the po/Makevars file. */
@ -501,8 +502,6 @@ void fatal (const floc *flocp, size_t length, const char *fmt, ...)
#define ONS(_t,_a,_f,_n,_s) _t((_a), INTSTR_LENGTH + strlen (_s), \
(_f), (_n), (_s))
#define OUT_OF_MEM() O (fatal, NILF, _("virtual memory exhausted"))
void die (int) __attribute__ ((noreturn));
void pfatal_with_name (const char *) __attribute__ ((noreturn));
void perror_with_name (const char *, const char *);

10
misc.c
View File

@ -220,7 +220,7 @@ xmalloc (unsigned int size)
/* Make sure we don't allocate 0, for pre-ISO implementations. */
void *result = malloc (size ? size : 1);
if (result == 0)
OUT_OF_MEM();
out_of_memory ();
return result;
}
@ -231,7 +231,7 @@ xcalloc (unsigned int size)
/* Make sure we don't allocate 0, for pre-ISO implementations. */
void *result = calloc (size ? size : 1, 1);
if (result == 0)
OUT_OF_MEM();
out_of_memory ();
return result;
}
@ -246,7 +246,7 @@ xrealloc (void *ptr, unsigned int size)
size = 1;
result = ptr ? realloc (ptr, size) : malloc (size);
if (result == 0)
OUT_OF_MEM();
out_of_memory ();
return result;
}
@ -263,7 +263,7 @@ xstrdup (const char *ptr)
#endif
if (result == 0)
OUT_OF_MEM();
out_of_memory ();
#ifdef HAVE_STRDUP
return result;
@ -282,7 +282,7 @@ xstrndup (const char *str, unsigned int length)
#ifdef HAVE_STRNDUP
result = strndup (str, length);
if (result == 0)
OUT_OF_MEM();
out_of_memory ();
#else
result = xmalloc (length + 1);
if (length > 0)

View File

@ -61,6 +61,26 @@ unsigned int stdio_traced = 0;
# define MODE_T int
#endif
/* Write a BUFFER of size LEN to file descriptor FD.
Handle EINTR and other short writes. If we get an error, ignore it. */
int
output_write (int fd, const void *buffer, size_t len)
{
const char *msg = buffer;
while (1)
{
ssize_t r;
EINTRLOOP (r, write (fd, msg, len));
if (r < 0 || (size_t)r == len)
return r;
len -= r;
msg += r;
}
}
/* Write a string to the current STDOUT or STDERR. */
static void
_outputs (struct output *out, int is_err, const char *msg)
@ -76,16 +96,8 @@ _outputs (struct output *out, int is_err, const char *msg)
int fd = is_err ? out->err : out->out;
int len = strlen (msg);
int r;
EINTRLOOP (r, lseek (fd, 0, SEEK_END));
while (1)
{
EINTRLOOP (r, write (fd, msg, len));
if (r == len || r <= 0)
break;
len -= r;
msg += r;
}
output_write (fd, msg, len);
}
}
@ -745,3 +757,15 @@ pfatal_with_name (const char *name)
/* NOTREACHED */
}
/* Print a message about out of memory (not using more heap) and exit.
Our goal here is to be sure we don't try to allocate more memory, which
means we don't want to use string translations or normal cleanup. */
void
out_of_memory ()
{
output_write (FD_STDOUT, program, strlen (program));
output_write (FD_STDOUT, STRING_SIZE_TUPLE (": *** virtual memory exhausted\n"));
exit (MAKE_FAILURE);
}

View File

@ -24,6 +24,10 @@ struct output
extern struct output *output_context;
extern unsigned int stdio_traced;
#define FD_STDIN (fileno (stdin))
#define FD_STDOUT (fileno (stdout))
#define FD_STDERR (fileno (stderr))
#define OUTPUT_SET(_new) do{ output_context = (_new)->syncout ? (_new) : NULL; }while(0)
#define OUTPUT_UNSET() do{ output_context = NULL; }while(0)
@ -32,6 +36,10 @@ extern unsigned int stdio_traced;
FILE *output_tmpfile (char **, const char *);
/* Write a buffer directly to the given file descriptor.
This handles errors etc. */
int output_write (int fd, const void *buffer, size_t len);
/* Initialize and close a child output structure: if NULL do this program's
output (this should only be done once). */
void output_init (struct output *out);

2
read.c
View File

@ -3276,7 +3276,7 @@ parse_file_seq (char **stringp, unsigned int size, int stopmap,
switch (glob (name, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl))
{
case GLOB_NOSPACE:
OUT_OF_MEM();
out_of_memory ();
case 0:
/* Success. */