Skip to content

Commit 9d6c4fa

Browse files
Make do_builtin_io multi-fork safe, moved it to postfork.cpp
Addresses fish-shell#495
1 parent b66233d commit 9d6c4fa

File tree

6 files changed

+35
-38
lines changed

6 files changed

+35
-38
lines changed

common.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ static char *wcs2str_internal(const wchar_t *in, char *out);
105105

106106
void show_stackframe()
107107
{
108+
ASSERT_IS_NOT_FORKED_CHILD();
109+
108110
/* Hack to avoid showing backtraces in the tester */
109111
if (program_name && ! wcscmp(program_name, L"(ignore)"))
110112
return;

exec.cpp

+5-28
Original file line numberDiff line numberDiff line change
@@ -497,32 +497,6 @@ static void internal_exec_helper(parser_t &parser,
497497
is_block=is_block_old;
498498
}
499499

500-
/** Perform output from builtins. Called from a forked child, so don't do anything that may allocate memory, etc.. */
501-
static void do_builtin_io(const char *out, size_t outlen, const char *err, size_t errlen)
502-
{
503-
if (out && outlen)
504-
{
505-
506-
if (write_loop(STDOUT_FILENO, out, outlen) == -1)
507-
{
508-
debug(0, L"Error while writing to stdout");
509-
wperror(L"write_loop");
510-
show_stackframe();
511-
}
512-
}
513-
514-
if (err && errlen)
515-
{
516-
if (write_loop(STDERR_FILENO, err, errlen) == -1)
517-
{
518-
/*
519-
Can't really show any error message here, since stderr is
520-
dead.
521-
*/
522-
}
523-
}
524-
}
525-
526500
/* Returns whether we can use posix spawn for a given process in a given job.
527501
Per https://github.com/fish-shell/fish-shell/issues/364 , error handling for file redirections is too difficult with posix_spawn
528502
So in that case we use fork/exec
@@ -1177,7 +1151,11 @@ void exec(parser_t &parser, job_t *j)
11771151
const wcstring &out = get_stdout_buffer(), &err = get_stderr_buffer();
11781152
const std::string outbuff = wcs2string(out);
11791153
const std::string errbuff = wcs2string(err);
1180-
do_builtin_io(outbuff.data(), outbuff.size(), errbuff.data(), errbuff.size());
1154+
bool builtin_io_done = do_builtin_io(outbuff.data(), outbuff.size(), errbuff.data(), errbuff.size());
1155+
if (! builtin_io_done)
1156+
{
1157+
show_stackframe();
1158+
}
11811159
skip_fork = true;
11821160
}
11831161

@@ -1239,7 +1217,6 @@ void exec(parser_t &parser, job_t *j)
12391217
setup_child_process(j, p);
12401218
do_builtin_io(outbuff, outbuff_len, errbuff, errbuff_len);
12411219
exit_without_destructors(p->status);
1242-
12431220
}
12441221
else
12451222
{

postfork.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -599,3 +599,28 @@ void safe_report_exec_error(int err, const char *actual_cmd, char **argv, char *
599599
}
600600
}
601601
}
602+
603+
/** Perform output from builtins. May be called from a forked child, so don't do anything that may allocate memory, etc.. */
604+
bool do_builtin_io(const char *out, size_t outlen, const char *err, size_t errlen)
605+
{
606+
bool success = true;
607+
if (out && outlen)
608+
{
609+
610+
if (write_loop(STDOUT_FILENO, out, outlen) < 0)
611+
{
612+
debug(0, L"Error while writing to stdout");
613+
safe_perror("write_loop");
614+
success = false;
615+
}
616+
}
617+
618+
if (err && errlen)
619+
{
620+
if (write_loop(STDERR_FILENO, err, errlen) < 0)
621+
{
622+
success = false;
623+
}
624+
}
625+
return success;
626+
}

postfork.h

+3
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ int setup_child_process(job_t *j, process_t *p);
6565
*/
6666
pid_t execute_fork(bool wait_for_threads_to_die);
6767

68+
/* Perform output from builtins. Returns true on success. */
69+
bool do_builtin_io(const char *out, size_t outlen, const char *err, size_t errlen);
70+
6871
/** Report an error from failing to exec or posix_spawn a command */
6972
void safe_report_exec_error(int err, const char *actual_cmd, char **argv, char **envv);
7073

wutil.cpp

-9
Original file line numberDiff line numberDiff line change
@@ -455,15 +455,6 @@ const wchar_t *wgettext(const wchar_t *in)
455455
return val->c_str();
456456
}
457457

458-
wcstring wgettext2(const wcstring &in)
459-
{
460-
wgettext_init_if_necessary();
461-
std::string mbs_in = wcs2string(in);
462-
char *out = gettext(mbs_in.c_str());
463-
wcstring result = format_string(L"%s", out);
464-
return result;
465-
}
466-
467458
const wchar_t *wgetenv(const wcstring &name)
468459
{
469460
ASSERT_IS_MAIN_THREAD();

wutil.h

-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ std::wstring wbasename(const std::wstring &path);
135135
around gettext, like all other functions in this file.
136136
*/
137137
const wchar_t *wgettext(const wchar_t *in);
138-
wcstring wgettext2(const wcstring &in);
139138

140139
/**
141140
Wide character version of getenv

0 commit comments

Comments
 (0)