Big fat refactoring of how redirections work. In fish 1.x and 2.0.0, the redirections for a process were flattened into a big list associated with the job, so there was no way to tell which redirections applied to each process. Each process therefore got all the redirections associated with the job. See https://github.com/fish-shell/fish-shell/issues/877 for how this could manifest.

With this change, jobs only track their block-level redirections. Process level redirections are correctly associated with the process, and at exec time we stitch them together (block, pipe, and process redirects).

This fixes the weird issues where redirects bleed across pipelines (like #877), and also allows us to play with the order in which redirections are applied, since the final list is constructed right before it's needed.  This lets us put pipes after block level redirections but before process level redirections, so that a 2>&1-type redirection gets picked up after the pipe, i.e. it should fix https://github.com/fish-shell/fish-shell/issues/110

This is a significant change. The tests all pass. Cross your fingers.
This commit is contained in:
ridiculousfish
2013-08-19 16:16:41 -07:00
parent f4f2847662
commit 4899086b3c
11 changed files with 182 additions and 116 deletions

View File

@@ -292,7 +292,7 @@ static int handle_child_io(const io_chain_t &io_chain)
}
int setup_child_process(job_t *j, process_t *p)
int setup_child_process(job_t *j, process_t *p, const io_chain_t &io_chain)
{
bool ok=true;
@@ -303,7 +303,7 @@ int setup_child_process(job_t *j, process_t *p)
if (ok)
{
ok = (0 == handle_child_io(j->io_chain()));
ok = (0 == handle_child_io(io_chain));
if (p != 0 && ! ok)
{
exit_without_destructors(1);
@@ -379,7 +379,7 @@ pid_t execute_fork(bool wait_for_threads_to_die)
}
#if FISH_USE_POSIX_SPAWN
bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_file_actions_t *actions, job_t *j, process_t *p)
bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_file_actions_t *actions, job_t *j, process_t *p, const io_chain_t &io_chain)
{
/* Initialize the output */
if (posix_spawnattr_init(attr) != 0)
@@ -444,19 +444,19 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
err = posix_spawnattr_setsigmask(attr, &sigmask);
/* Make sure that our pipes don't use an fd that the redirection itself wants to use */
free_redirected_fds_from_pipes(j->io_chain());
free_redirected_fds_from_pipes(io_chain);
/* Close unused internal pipes */
std::vector<int> files_to_close;
get_unused_internal_pipes(files_to_close, j->io_chain());
get_unused_internal_pipes(files_to_close, io_chain);
for (size_t i = 0; ! err && i < files_to_close.size(); i++)
{
err = posix_spawn_file_actions_addclose(actions, files_to_close.at(i));
}
for (size_t idx = 0; idx < j->io_chain().size(); idx++)
for (size_t idx = 0; idx < io_chain.size(); idx++)
{
shared_ptr<const io_data_t> io = j->io_chain().at(idx);
const shared_ptr<const io_data_t> io = io_chain.at(idx);
if (io->io_mode == IO_FD)
{