mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-12 21:18:53 +00:00
Hopeful fix to avoid forking for certain builtins like echo when they have an input redirection only
This commit is contained in:
parent
3c8c8a7559
commit
9f8fe3d5e3
3 changed files with 26 additions and 14 deletions
26
exec.cpp
26
exec.cpp
|
@ -1159,23 +1159,25 @@ void exec(parser_t &parser, job_t *j)
|
||||||
performance quite a bit in complex completion code.
|
performance quite a bit in complex completion code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const shared_ptr<io_data_t> &io = io_chain_get(j->io, 1);
|
const shared_ptr<io_data_t> &stdout_io = io_chain_get(j->io, STDOUT_FILENO);
|
||||||
bool buffer_stdout = io && io->io_mode == IO_BUFFER;
|
const shared_ptr<io_data_t> &stderr_io = io_chain_get(j->io, STDERR_FILENO);
|
||||||
|
const bool buffer_stdout = stdout_io && stdout_io->io_mode == IO_BUFFER;
|
||||||
|
|
||||||
if ((get_stderr_buffer().empty()) &&
|
if ((get_stderr_buffer().empty()) &&
|
||||||
(!p->next) &&
|
(!p->next) &&
|
||||||
(! get_stdout_buffer().empty()) &&
|
(! get_stdout_buffer().empty()) &&
|
||||||
(buffer_stdout))
|
(buffer_stdout))
|
||||||
{
|
{
|
||||||
CAST_INIT(io_buffer_t *, io_buffer, io.get());
|
CAST_INIT(io_buffer_t *, io_buffer, stdout_io.get());
|
||||||
const std::string res = wcs2string(get_stdout_buffer());
|
const std::string res = wcs2string(get_stdout_buffer());
|
||||||
io_buffer->out_buffer_append(res.c_str(), res.size());
|
io_buffer->out_buffer_append(res.c_str(), res.size());
|
||||||
skip_fork = true;
|
skip_fork = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! skip_fork && j->io.empty())
|
/* PCA for some reason, fish forks a lot, even for basic builtins like echo just to write out their buffers. I'm certain a lot of this is unnecessary, but I am not sure exactly when. If j->io is NULL, then it means there's no pipes or anything, so we can certainly just write out our data. Beyond that, we may be able to do the same if io_get returns 0 for STDOUT_FILENO and STDERR_FILENO.
|
||||||
|
*/
|
||||||
|
if (! skip_fork && stdout_io.get() == NULL && stderr_io.get() == NULL)
|
||||||
{
|
{
|
||||||
/* PCA for some reason, fish forks a lot, even for basic builtins like echo just to write out their buffers. I'm certain a lot of this is unnecessary, but I am not sure exactly when. If j->io is NULL, then it means there's no pipes or anything, so we can certainly just write out our data. Beyond that, we may be able to do the same if io_get returns 0 for STDOUT_FILENO and STDERR_FILENO. */
|
|
||||||
if (g_log_forks)
|
if (g_log_forks)
|
||||||
{
|
{
|
||||||
printf("fork #-: Skipping fork for internal builtin for '%ls'\n", p->argv0());
|
printf("fork #-: Skipping fork for internal builtin for '%ls'\n", p->argv0());
|
||||||
|
@ -1194,10 +1196,14 @@ void exec(parser_t &parser, job_t *j)
|
||||||
for (io_chain_t::iterator iter = j->io.begin(); iter != j->io.end(); ++iter)
|
for (io_chain_t::iterator iter = j->io.begin(); iter != j->io.end(); ++iter)
|
||||||
{
|
{
|
||||||
const shared_ptr<io_data_t> &tmp_io = *iter;
|
const shared_ptr<io_data_t> &tmp_io = *iter;
|
||||||
if (tmp_io->io_mode == IO_FILE && strcmp(static_cast<const io_file_t *>(tmp_io.get())->filename_cstr, "/dev/null") != 0)
|
if (tmp_io->io_mode == IO_FILE)
|
||||||
{
|
{
|
||||||
skip_fork = false;
|
const io_file_t *tmp_file_io = static_cast<const io_file_t *>(tmp_io.get());
|
||||||
break;
|
if (strcmp(tmp_file_io->filename_cstr, "/dev/null"))
|
||||||
|
{
|
||||||
|
skip_fork = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,7 +1241,7 @@ void exec(parser_t &parser, job_t *j)
|
||||||
if (g_log_forks)
|
if (g_log_forks)
|
||||||
{
|
{
|
||||||
printf("fork #%d: Executing fork for internal builtin for '%ls'\n", g_fork_count, p->argv0());
|
printf("fork #%d: Executing fork for internal builtin for '%ls'\n", g_fork_count, p->argv0());
|
||||||
io_print(io_chain_t(io));
|
io_print(j->io);
|
||||||
}
|
}
|
||||||
pid = execute_fork(false);
|
pid = execute_fork(false);
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
|
|
13
io.cpp
13
io.cpp
|
@ -209,7 +209,7 @@ void io_chain_t::push_back(const shared_ptr<io_data_t> &element)
|
||||||
{
|
{
|
||||||
// Ensure we never push back NULL
|
// Ensure we never push back NULL
|
||||||
assert(element.get() != NULL);
|
assert(element.get() != NULL);
|
||||||
std::vector<shared_ptr<io_data_t> >:: push_back(element);
|
std::vector<shared_ptr<io_data_t> >::push_back(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
void io_remove(io_chain_t &list, const shared_ptr<const io_data_t> &element)
|
void io_remove(io_chain_t &list, const shared_ptr<const io_data_t> &element)
|
||||||
|
@ -229,8 +229,15 @@ void io_print(const io_chain_t &chain)
|
||||||
for (size_t i=0; i < chain.size(); i++)
|
for (size_t i=0; i < chain.size(); i++)
|
||||||
{
|
{
|
||||||
const shared_ptr<const io_data_t> &io = chain.at(i);
|
const shared_ptr<const io_data_t> &io = chain.at(i);
|
||||||
fprintf(stderr, "\t%lu: fd:%d, ", (unsigned long)i, io->fd);
|
if (io.get() == NULL)
|
||||||
io->print();
|
{
|
||||||
|
fprintf(stderr, "\t(null)\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "\t%lu: fd:%d, ", (unsigned long)i, io->fd);
|
||||||
|
io->print();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
io.h
1
io.h
|
@ -184,7 +184,6 @@ public:
|
||||||
|
|
||||||
shared_ptr<const io_data_t> get_io_for_fd(int fd) const;
|
shared_ptr<const io_data_t> get_io_for_fd(int fd) const;
|
||||||
shared_ptr<io_data_t> get_io_for_fd(int fd);
|
shared_ptr<io_data_t> get_io_for_fd(int fd);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue