From 6e432f0cda1daa7bcee1fb5872dcfa130abe5018 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 13 Feb 2013 19:00:26 +0200 Subject: Cleanup related to bug #13546 with subprocesses on MS-Windows. src/w32.c (sys_pipe): When failing due to file descriptors above MAXDESC, set errno to EMFILE. (_sys_read_ahead): Update cp->status when failing to read serial communications input, so that the status doesn't stay at STATUS_READ_IN_PROGRESS. --- src/ChangeLog | 8 ++++++++ src/w32.c | 21 +++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 62d33e15ece..358f25b40f9 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2013-02-13 Eli Zaretskii + + * w32.c (sys_pipe): When failing due to file descriptors above + MAXDESC, set errno to EMFILE. + (_sys_read_ahead): Update cp->status when failing to read serial + communications input, so that the status doesn't stay at + STATUS_READ_IN_PROGRESS. (Bug#13546) + 2013-02-13 Glenn Morris * keyboard.c (input-decode-map, key-translation-map): Doc fixes. diff --git a/src/w32.c b/src/w32.c index 802403168f0..214fb7fdfae 100644 --- a/src/w32.c +++ b/src/w32.c @@ -6209,6 +6209,7 @@ sys_pipe (int * phandles) { _close (phandles[0]); _close (phandles[1]); + errno = EMFILE; rc = -1; } else @@ -6281,19 +6282,31 @@ _sys_read_ahead (int fd) /* Configure timeouts for blocking read. */ if (!GetCommTimeouts (hnd, &ct)) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } ct.ReadIntervalTimeout = 0; ct.ReadTotalTimeoutMultiplier = 0; ct.ReadTotalTimeoutConstant = 0; if (!SetCommTimeouts (hnd, &ct)) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl)) { if (GetLastError () != ERROR_IO_PENDING) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE)) - return STATUS_READ_ERROR; + { + cp->status = STATUS_READ_ERROR; + return STATUS_READ_ERROR; + } } } else if (fd_info[fd].flags & FILE_SOCKET) -- cgit v1.2.1 From 0e4e7b741b515be091e2ec3b3ff63f1b16084555 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 13 Feb 2013 19:04:30 +0200 Subject: More robust creation of a subprocess, attempt to solve bug #13546. src/w32proc.c (new_child): If no vacant slots are found in child_procs[], make another pass looking for slots whose process has exited or died. --- src/ChangeLog | 4 ++++ src/w32proc.c | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 358f25b40f9..e1b8a23e6b2 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,9 @@ 2013-02-13 Eli Zaretskii + * w32proc.c (new_child): If no vacant slots are found in + child_procs[], make another pass looking for slots whose process + has exited or died. (Bug#13546) + * w32.c (sys_pipe): When failing due to file descriptors above MAXDESC, set errno to EMFILE. (_sys_read_ahead): Update cp->status when failing to read serial diff --git a/src/w32proc.c b/src/w32proc.c index 8c09a1b1beb..1e72d41e16b 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -797,6 +797,33 @@ new_child (void) for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess == NULL) goto Initialize; + if (child_proc_count == MAX_CHILDREN) + { + DebPrint (("new_child: No vacant slots, looking for dead processes\n")); + for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) + if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess) + { + DWORD status = 0; + + if (!GetExitCodeProcess (cp->procinfo.hProcess, &status)) + { + DebPrint (("new_child.GetExitCodeProcess: error %lu for PID %lu\n", + GetLastError (), cp->procinfo.dwProcessId)); + status = STILL_ACTIVE; + } + if (status != STILL_ACTIVE + || WaitForSingleObject (cp->procinfo.hProcess, 0) == WAIT_OBJECT_0) + { + DebPrint (("new_child: Freeing slot of dead process %d\n", + cp->procinfo.dwProcessId)); + CloseHandle (cp->procinfo.hProcess); + cp->procinfo.hProcess = NULL; + CloseHandle (cp->procinfo.hThread); + cp->procinfo.hThread = NULL; + goto Initialize; + } + } + } if (child_proc_count == MAX_CHILDREN) return NULL; cp = &child_procs[child_proc_count++]; -- cgit v1.2.1 From 35b3a27e67b60e547ac8bc9388e7724d1f829959 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 14 Feb 2013 12:05:10 -0800 Subject: Fix AIX port. * configure.ac (DATA_START, DATA_SEG_BITS): Set to 0x20000000 on AIX. (GC_MARK_STACK): Do not set to GC_USE_GCPROS_AS_BEFORE, as that runs afoul of some other bug in Emacs, and the default value GC_MAKE_GCPROS_NOOPS has been tested and works. * src/lisp.h (XPNTR) [!USE_LSB_TAG && DATA_SEG_BITS]: Fix bug introduced in 2012-07-27 change. DATA_SEG_BITS, if set, was #undeffed earlier, so it cannot be used as a macro here. Use the constant and not the macro. Tested on AIX. * src/unexaix.c: Revert 2013-02-11 and 2013-02-12 changes to this file. They're almost surely OK but we're just before a release so we should avoid changes unless they're clearly needed. Instead, make the following minor change: (ADDR_CORRECT): New macro. Fixes: debbugs:13650 --- src/ChangeLog | 13 ++++++++ src/lisp.h | 4 --- src/unexaix.c | 96 +++++++++++++++++++++++++++++++---------------------------- 3 files changed, 64 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index e1b8a23e6b2..e283d2bb48c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2013-02-14 Paul Eggert + + Fix AIX port (Bug#13650). + * lisp.h (XPNTR) [!USE_LSB_TAG && DATA_SEG_BITS]: + Fix bug introduced in 2012-07-27 change. DATA_SEG_BITS, if set, + was #undeffed earlier, so it cannot be used as a macro here. + Use the constant and not the macro. + * unexaix.c: Revert 2013-02-11 and 2013-02-12 changes to this + file. They're almost surely OK but we're just before a release so + we should avoid changes unless they're clearly needed. Instead, + make the following minor change: + (ADDR_CORRECT): New macro. + 2013-02-13 Eli Zaretskii * w32proc.c (new_child): If no vacant slots are found in diff --git a/src/lisp.h b/src/lisp.h index a62842c117a..eca3caefd8c 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -496,13 +496,9 @@ static EMACS_INT const VALMASK (XIL ((EMACS_INT) ((EMACS_UINT) (type) << VALBITS) \ + ((intptr_t) (ptr) & VALMASK))) -#if DATA_SEG_BITS /* DATA_SEG_BITS forces extra bits to be or'd in with any pointers which were stored in a Lisp_Object. */ #define XPNTR(a) ((uintptr_t) ((XLI (a) & VALMASK)) | DATA_SEG_BITS)) -#else -#define XPNTR(a) ((uintptr_t) (XLI (a) & VALMASK)) -#endif #endif /* not USE_LSB_TAG */ diff --git a/src/unexaix.c b/src/unexaix.c index da44480fdca..885d7a9f6d7 100644 --- a/src/unexaix.c +++ b/src/unexaix.c @@ -51,8 +51,6 @@ what you give them. Help stamp out software-hoarding! */ #include "getpagesize.h" #include -#include -#include #include #include #include @@ -61,8 +59,10 @@ what you give them. Help stamp out software-hoarding! */ #include "mem-limits.h" -extern char _data[]; -extern char _text[]; +char *start_of_text (void); /* Start of text */ + +extern int _data; +extern int _text; #include #include @@ -71,15 +71,15 @@ extern char _text[]; static struct filehdr f_hdr; /* File header */ static struct aouthdr f_ohdr; /* Optional file header (a.out) */ -static off_t bias; /* Bias to add for growth */ -static off_t lnnoptr; /* Pointer to line-number info within file */ +static long bias; /* Bias to add for growth */ +static long lnnoptr; /* Pointer to line-number info within file */ -static off_t text_scnptr; -static off_t data_scnptr; +static long text_scnptr; +static long data_scnptr; #define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1)) -static off_t load_scnptr; -static off_t orig_load_scnptr; -static off_t orig_data_scnptr; +static long load_scnptr; +static long orig_load_scnptr; +static long orig_data_scnptr; static int unrelocate_symbols (int, int, const char *, const char *); #ifndef MAX_SECTIONS @@ -92,30 +92,26 @@ static int pagemask; #include "lisp.h" -static _Noreturn void +static void report_error (const char *file, int fd) { if (fd) - { - int failed_errno = errno; - close (fd); - errno = failed_errno; - } + close (fd); report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil)); } -#define ERROR0(msg) report_error_1 (new, msg) -#define ERROR1(msg,x) report_error_1 (new, msg, x) -#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y) +#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1 +#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1 +#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1 -static _Noreturn void ATTRIBUTE_FORMAT_PRINTF (2, 3) -report_error_1 (int fd, const char *msg, ...) +#undef ADDR_CORRECT +#define ADDR_CORRECT(x) ((int)(x)) + +static void +report_error_1 (int fd, const char *msg, int a1, int a2) { - va_list ap; close (fd); - va_start (ap, msg); - verror (msg, ap); - va_end (ap); + error (msg, a1, a2); } static int make_hdr (int, int, const char *, const char *); @@ -170,8 +166,8 @@ make_hdr (int new, int a_out, const char *a_name, const char *new_name) { int scns; - uintptr_t bss_start; - uintptr_t data_start; + unsigned int bss_start; + unsigned int data_start; struct scnhdr section[MAX_SECTIONS]; struct scnhdr * f_thdr; /* Text section header */ @@ -186,17 +182,17 @@ make_hdr (int new, int a_out, pagemask = getpagesize () - 1; /* Adjust text/data boundary. */ - data_start = (uintptr_t) _data; + data_start = (long) start_of_data (); + data_start = ADDR_CORRECT (data_start); data_start = data_start & ~pagemask; /* (Down) to page boundary. */ - bss_start = (uintptr_t) sbrk (0) + pagemask; + bss_start = ADDR_CORRECT (sbrk (0)) + pagemask; bss_start &= ~ pagemask; if (data_start > bss_start) /* Can't have negative data size. */ { - ERROR2 (("unexec: data_start (0x%"PRIxPTR - ") can't be greater than bss_start (0x%"PRIxPTR")"), + ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)", data_start, bss_start); } @@ -286,7 +282,7 @@ make_hdr (int new, int a_out, /* fix scnptr's */ { - off_t ptr = section[0].s_scnptr; + ulong ptr = section[0].s_scnptr; bias = -1; for (scns = 0; scns < f_hdr.f_nscns; scns++) @@ -382,12 +378,12 @@ copy_text_and_data (int new) char *end; char *ptr; - lseek (new, text_scnptr, SEEK_SET); - ptr = _text + text_scnptr; + lseek (new, (long) text_scnptr, SEEK_SET); + ptr = start_of_text () + text_scnptr; end = ptr + f_ohdr.tsize; write_segment (new, ptr, end); - lseek (new, data_scnptr, SEEK_SET); + lseek (new, (long) data_scnptr, SEEK_SET); ptr = (char *) f_ohdr.data_start; end = ptr + f_ohdr.dsize; write_segment (new, ptr, end); @@ -400,6 +396,7 @@ static void write_segment (int new, char *ptr, char *end) { int i, nwrite, ret; + char buf[80]; char zeros[UnexBlockSz]; for (i = 0; ptr < end;) @@ -420,13 +417,9 @@ write_segment (int new, char *ptr, char *end) } else if (nwrite != ret) { - int write_errno = errno; - char buf[1000]; - void *addr = ptr; sprintf (buf, - "unexec write failure: addr %p, fileno %d, size 0x%x, wrote 0x%x, errno %d", - addr, new, nwrite, ret, errno); - errno = write_errno; + "unexec write failure: addr 0x%lx, fileno %d, size 0x%x, wrote 0x%x, errno %d", + (unsigned long)ptr, new, nwrite, ret, errno); PERROR (buf); } i += nwrite; @@ -547,13 +540,13 @@ unrelocate_symbols (int new, int a_out, int i; LDHDR ldhdr; LDREL ldrel; - off_t t_reloc = (intptr_t) _text - f_ohdr.text_start; + ulong t_reloc = (ulong) &_text - f_ohdr.text_start; #ifndef ALIGN_DATA_RELOC - off_t d_reloc = (intptr_t) _data - f_ohdr.data_start; + ulong d_reloc = (ulong) &_data - f_ohdr.data_start; #else /* This worked (and was needed) before AIX 4.2. I have no idea why. -- Mike */ - off_t d_reloc = (intptr_t) _data - ALIGN (f_ohdr.data_start, 2); + ulong d_reloc = (ulong) &_data - ALIGN (f_ohdr.data_start, 2); #endif int * p; @@ -638,3 +631,16 @@ unrelocate_symbols (int new, int a_out, } return 0; } + +/* + * Return the address of the start of the text segment prior to + * doing an unexec. After unexec the return value is undefined. + * See crt0.c for further explanation and _start. + * + */ + +char * +start_of_text (void) +{ + return ((char *) 0x10000000); +} -- cgit v1.2.1 From 974c7646ec5b2985a50007c9d599154d667df349 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 14 Feb 2013 14:08:38 -0800 Subject: Backport GCPRO fix from trunk. The bug was reported for AIX before today's changes. I reproduced the problem on Fedora 17 x86-64 when setting GC_MARK_STACK by hand, and I presume it occurs with default configurations on HP-UX and Unixware. Trunk fix on 2013-01-14 by Dmitry Antipov : Fix compilation with GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE. * eval.c (eval_sub): Protect `form' from being GCed before its car and cdr becomes protected with the backtrace entry. Fixes: debbugs:13650 --- src/ChangeLog | 10 ++++++++++ src/eval.c | 3 +++ 2 files changed, 13 insertions(+) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index e283d2bb48c..46a466d060d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,15 @@ 2013-02-14 Paul Eggert + Backport GCPRO fix from trunk (Bug#13650). + The bug was reported for AIX before today's changes. + I reproduced the problem on Fedora 17 x86-64 when setting + GC_MARK_STACK by hand, and I presume it occurs with default + configurations on HP-UX and Unixware. + Trunk fix on 2013-01-14 by Dmitry Antipov : + Fix compilation with GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE. + * eval.c (eval_sub): Protect `form' from being GCed before its + car and cdr becomes protected with the backtrace entry. + Fix AIX port (Bug#13650). * lisp.h (XPNTR) [!USE_LSB_TAG && DATA_SEG_BITS]: Fix bug introduced in 2012-07-27 change. DATA_SEG_BITS, if set, diff --git a/src/eval.c b/src/eval.c index a0db6e0745c..a21b2b05762 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2034,7 +2034,10 @@ eval_sub (Lisp_Object form) return form; QUIT; + + GCPRO1 (form); maybe_gc (); + UNGCPRO; if (++lisp_eval_depth > max_lisp_eval_depth) { -- cgit v1.2.1