mirror of
https://github.com/mirror/make.git
synced 2025-03-04 14:51:11 +08:00
[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:
parent
2b8e3bb23f
commit
68be4f74fc
6
arscan.c
6
arscan.c
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
3
job.h
@ -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
|
||||
|
||||
|
@ -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
10
misc.c
@ -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)
|
||||
|
42
output.c
42
output.c
@ -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);
|
||||
}
|
||||
|
8
output.h
8
output.h
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user