mirror of
https://github.com/sheumann/hush.git
synced 2024-12-23 20:29:42 +00:00
Fix corruption and hanging resulting from using _exit in forked processes by calling QuitGS directly instead.
GNO's _exit (contrary to its man page) does clean-up for stuff like the memory allocator, which is inappropriate in a forked child process and leads to hangs and crashes.
This commit is contained in:
parent
b3a419646b
commit
6d5e65b9df
@ -1641,6 +1641,13 @@ int signal_parent_to_resume(void);
|
|||||||
/* Get path of current executable */
|
/* Get path of current executable */
|
||||||
char *get_exec_path(void);
|
char *get_exec_path(void);
|
||||||
|
|
||||||
|
/* On GNO, we need to use this wrapper because _exit is broken when
|
||||||
|
* called from forked child processes. */
|
||||||
|
#ifdef __GNO__
|
||||||
|
void _exit_wrapper(int status) NORETURN;
|
||||||
|
# define _exit(s) _exit_wrapper(s)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Simple unit-testing framework */
|
/* Simple unit-testing framework */
|
||||||
|
|
||||||
typedef void (*bbunit_testfunc)(void);
|
typedef void (*bbunit_testfunc)(void);
|
||||||
|
37
shell/hush.c
37
shell/hush.c
@ -1356,6 +1356,43 @@ int signal_parent_to_resume(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNO__
|
||||||
|
#undef _exit
|
||||||
|
|
||||||
|
#include <gsos.h>
|
||||||
|
static QuitRecGS quitRec = {0, NULL, 0};
|
||||||
|
|
||||||
|
/* _exit (contrary to its documentation) performs clean-up that's
|
||||||
|
* inappropriate for a forked child process (this usually results
|
||||||
|
* in corruption of the memory allocator state, and maybe other
|
||||||
|
* problems), so we define our own version without this problem.
|
||||||
|
*/
|
||||||
|
void _exit_wrapper(int status) {
|
||||||
|
if (getpid() == G.last_execed_pid) {
|
||||||
|
// We're the root shell or one that's been exec'd...
|
||||||
|
// Call regular _exit()
|
||||||
|
_exit(status);
|
||||||
|
} else {
|
||||||
|
// We're a forked child. Just call QuitGS. We do it in
|
||||||
|
// assembly so we can push the return value on the stack.
|
||||||
|
while (1) {
|
||||||
|
asm {
|
||||||
|
lda status
|
||||||
|
pha
|
||||||
|
jsl 0xE100A8
|
||||||
|
dcw 0x2029 /* QuitGS */
|
||||||
|
dcl quitRec;
|
||||||
|
pla
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _exit(s) _exit_wrapper(s)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Basic theory of signal handling in shell
|
/* Basic theory of signal handling in shell
|
||||||
* ========================================
|
* ========================================
|
||||||
* This does not describe what hush does, rather, it is current understanding
|
* This does not describe what hush does, rather, it is current understanding
|
||||||
|
Loading…
Reference in New Issue
Block a user