本文整理汇总了C++中io_chain_t类的典型用法代码示例。如果您正苦于以下问题:C++ io_chain_t类的具体用法?C++ io_chain_t怎么用?C++ io_chain_t使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了io_chain_t类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: read_try
/**
Read from descriptors until they are empty.
\param j the job to test
*/
static void read_try(job_t *j)
{
io_buffer_t *buff = NULL;
/*
Find the last buffer, which is the one we want to read from
*/
const io_chain_t chain = j->all_io_redirections();
for (size_t idx = 0; idx < chain.size(); idx++)
{
io_data_t *d = chain.at(idx).get();
if (d->io_mode == IO_BUFFER)
{
buff = static_cast<io_buffer_t *>(d);
}
}
if (buff)
{
debug(3, L"proc::read_try('%ls')\n", j->command_wcstr());
while (1)
{
char b[BUFFER_SIZE];
long l;
l=read_blocked(buff->pipe_fd[0],
b, BUFFER_SIZE);
if (l==0)
{
break;
}
else if (l<0)
{
if (errno != EAGAIN)
{
debug(1,
_(L"An error occured while reading output from code block"));
wperror(L"read_try");
}
break;
}
else
{
buff->out_buffer_append(b, l);
}
}
}
}
示例2: move_fd_to_unused
int move_fd_to_unused(int fd, const io_chain_t &io_chain, bool cloexec) {
if (fd < 0 || io_chain.get_io_for_fd(fd).get() == NULL) {
return fd;
}
// We have fd >= 0, and it's a conflict. dup it and recurse. Note that we recurse before
// anything is closed; this forces the kernel to give us a new one (or report fd exhaustion).
int new_fd = fd;
int tmp_fd;
do {
tmp_fd = dup(fd);
} while (tmp_fd < 0 && errno == EINTR);
assert(tmp_fd != fd);
if (tmp_fd < 0) {
// Likely fd exhaustion.
new_fd = -1;
} else {
// Ok, we have a new candidate fd. Recurse. If we get a valid fd, either it's the same as
// what we gave it, or it's a new fd and what we gave it has been closed. If we get a
// negative value, the fd also has been closed.
if (cloexec) set_cloexec(tmp_fd);
new_fd = move_fd_to_unused(tmp_fd, io_chain);
}
// We're either returning a new fd or an error. In both cases, we promise to close the old one.
assert(new_fd != fd);
int saved_errno = errno;
exec_close(fd);
errno = saved_errno;
return new_fd;
}
示例3: io_print
void io_print(const io_chain_t &chain)
{
if (chain.empty())
{
fprintf(stderr, "Empty chain %p\n", &chain);
return;
}
fprintf(stderr, "Chain %p (%ld items):\n", &chain, (long)chain.size());
for (size_t i=0; i < chain.size(); i++)
{
const shared_ptr<const io_data_t> &io = chain.at(i);
fprintf(stderr, "\t%lu: fd:%d, ", (unsigned long)i, io->fd);
io->print();
}
}
示例4: free_redirected_fds_from_pipes
/** Make sure the fd used by each redirection is not used by a pipe. Note that while this does not modify the vector, it does modify the IO redirections within (gulp) */
static void free_redirected_fds_from_pipes(const io_chain_t &io_chain)
{
size_t max = io_chain.size();
for (size_t i = 0; i < max; i++)
{
int fd_to_free = io_chain.at(i)->fd;
/* We only have to worry about fds beyond the three standard ones */
if (fd_to_free <= 2)
continue;
/* Make sure the fd is not used by a pipe */
for (size_t j = 0; j < max; j++)
{
/* We're only interested in pipes */
io_data_t *io = io_chain.at(j).get();
if (io->io_mode != IO_PIPE && io->io_mode != IO_BUFFER)
continue;
CAST_INIT(io_pipe_t *, possible_conflict, io);
/* If the pipe is a conflict, dup it to some other value */
for (int k=0; k<2; k++)
{
/* If it's not a conflict, we don't care */
if (possible_conflict->pipe_fd[k] != fd_to_free)
continue;
/* Repeat until we have a replacement fd */
int replacement_fd = -1;
while (replacement_fd < 0)
{
replacement_fd = dup(fd_to_free);
if (replacement_fd == -1 && errno != EINTR)
{
debug_safe_int(1, FD_ERROR, fd_to_free);
safe_perror("dup");
FATAL_EXIT();
}
}
possible_conflict->pipe_fd[k] = replacement_fd;
}
}
}
}
示例5: select_try
/**
Check if there are buffers associated with the job, and select on
them for a while if available.
\param j the job to test
\return 1 if buffers were available, zero otherwise
*/
static int select_try(job_t *j)
{
fd_set fds;
int maxfd=-1;
FD_ZERO(&fds);
const io_chain_t chain = j->all_io_redirections();
for (size_t idx = 0; idx < chain.size(); idx++)
{
const io_data_t *io = chain.at(idx).get();
if (io->io_mode == IO_BUFFER)
{
CAST_INIT(const io_pipe_t *, io_pipe, io);
int fd = io_pipe->pipe_fd[0];
// fwprintf( stderr, L"fd %d on job %ls\n", fd, j->command );
FD_SET(fd, &fds);
maxfd = maxi(maxfd, fd);
debug(3, L"select_try on %d\n", fd);
}
}
if (maxfd >= 0)
{
int retval;
struct timeval tv;
tv.tv_sec=0;
tv.tv_usec=10000;
retval =select(maxfd+1, &fds, 0, 0, &tv);
if (retval == 0) {
debug(3, L"select_try hit timeout\n");
}
return retval > 0;
}
return -1;
}
示例6: io_print
// This isn't used so the lint tools were complaining about its presence. I'm keeping it in the
// source because it could be useful for debugging.
void io_print(const io_chain_t &chain)
{
if (chain.empty())
{
std::fwprintf(stderr, L"Empty chain %p\n", &chain);
return;
}
std::fwprintf(stderr, L"Chain %p (%ld items):\n", &chain, (long)chain.size());
for (size_t i=0; i < chain.size(); i++)
{
const shared_ptr<io_data_t> &io = chain.at(i);
if (io.get() == NULL)
{
std::fwprintf(stderr, L"\t(null)\n");
}
else
{
std::fwprintf(stderr, L"\t%lu: fd:%d, ", (unsigned long)i, io->fd);
io->print();
}
}
}
示例7: io_chain_destroy
void io_chain_destroy(io_chain_t &chain)
{
chain.destroy();
}
示例8: io_duplicate_prepend
void io_duplicate_prepend(const io_chain_t &src, io_chain_t &dst)
{
return dst.duplicate_prepend(src);
}
示例9: io_duplicate
io_chain_t io_duplicate(const io_chain_t &chain)
{
return chain.duplicate();
}
示例10: io_remove
void io_remove(io_chain_t &list, const io_data_t *element)
{
list.remove(element);
}
示例11: exec_job
void exec_job(parser_t &parser, shared_ptr<job_t> j) {
assert(j && "null job_t passed to exec_job!");
// Set to true if something goes wrong while exec:ing the job, in which case the cleanup code
// will kick in.
bool exec_error = false;
// If fish was invoked with -n or --no-execute, then no_exec will be set and we do nothing.
if (no_exec) {
return;
}
// Unfortunately `exec_job()` is called recursively when functions are encountered, with a new
// job id (and therefore pgrp) each time, but always from the main thread. This breaks terminal
// control since new pgrps take terminal control away from commands upstream in a different pgrp.
// We try to work around this with a heuristic to determine whether to reuse the same pgrp as the
// last-spawned pgrp if part of an existing job pipeline (keeping in mind that new jobs are
// recursively started for both foreground and background jobs, and that a function can expand
// to more than one external command, one (or more?) of which may want to read from upstream or
// write to downstream of a pipe.
// By keeping track of (select) "jobs in flight" we can try to marshall newly-created external
// processes into existing pgrps. Fixes #3952.
// This is a HACK and the correct solution would be to pass the active job through the pipeline
// to the newly established parser context so that the funtion as parsed and evaluated can be
// directly associated with this job and not a new one, BUT sometimes functions NEED to start a
// new job. This HACK seeks a compromise by letting functions trigger the unilateral creation of
// a new job, but reusing the "parent" job's existing pgrp in case of terminal control.
static std::stack<decltype(j)> active_jobs;
// There's an assumption that there's a one-to-one mapping between jobs under job control and
// pgrps. When we share a parent job's pgrp, we risk reaping its processes before it is fully
// constructed, causing later setpgrp(2) calls to fails (#5219). While the parent job is still
// under construction, child jobs have job_flag_t::WAIT_BY_PROCESS set to prevent early repaing.
// We store them here until the parent job is constructed, at which point it unsets this flag.
static std::stack<decltype(j)> child_jobs;
auto parent_job = active_jobs.empty() ? nullptr : active_jobs.top();
bool job_pushed = false;
if (j->get_flag(job_flag_t::TERMINAL) && j->get_flag(job_flag_t::JOB_CONTROL)) {
// This will be popped before this job leaves exec_job
active_jobs.push(j);
job_pushed = true;
}
if (parent_job && j->processes.front()->type == EXTERNAL) {
if (parent_job->pgid != INVALID_PID) {
j->pgid = parent_job->pgid;
j->set_flag(job_flag_t::JOB_CONTROL, true);
j->set_flag(job_flag_t::NESTED, true);
j->set_flag(job_flag_t::WAIT_BY_PROCESS, true);
child_jobs.push(j);
}
}
// Verify that all IO_BUFFERs are output. We used to support a (single, hacked-in) magical input
// IO_BUFFER used by fish_pager, but now the claim is that there are no more clients and it is
// removed. This assertion double-checks that.
size_t stdout_read_limit = 0;
const io_chain_t all_ios = j->all_io_redirections();
for (size_t idx = 0; idx < all_ios.size(); idx++) {
const shared_ptr<io_data_t> &io = all_ios.at(idx);
if ((io->io_mode == IO_BUFFER)) {
io_buffer_t *io_buffer = static_cast<io_buffer_t *>(io.get());
assert(!io_buffer->is_input);
stdout_read_limit = io_buffer->buffer().limit();
}
}
if (j->processes.front()->type == INTERNAL_EXEC) {
internal_exec(j.get(), std::move(all_ios));
DIE("this should be unreachable");
}
// We may have block IOs that conflict with fd redirections. For example, we may have a command
// with a redireciton like <&3; we may also have chosen 3 as the fd for our pipe. Ensure we have
// no conflicts.
for (const auto io : all_ios) {
if (io->io_mode == IO_BUFFER) {
auto *io_buffer = static_cast<io_buffer_t *>(io.get());
if (!io_buffer->avoid_conflicts_with_io_chain(all_ios)) {
// We could not avoid conflicts, probably due to fd exhaustion. Mark an error.
exec_error = true;
job_mark_process_as_failed(j.get(), j->processes.front().get());
break;
}
}
}
// This loop loops over every process_t in the job, starting it as appropriate. This turns out
// to be rather complex, since a process_t can be one of many rather different things.
//
// The loop also has to handle pipelining between the jobs.
//
// We can have up to three pipes "in flight" at a time:
//
// 1. The pipe the current process should read from (courtesy of the previous process)
// 2. The pipe that the current process should write to
// 3. The pipe that the next process should read from (courtesy of us)
//
autoclose_fd_t pipe_next_read;
//.........这里部分代码省略.........
示例12: setup_child_process
/**
Set up a childs io redirections. Should only be called by
setup_child_process(). Does the following: First it closes any open
file descriptors not related to the child by calling
close_unused_internal_pipes() and closing the universal variable
server file descriptor. It then goes on to perform all the
redirections described by \c io.
\param io the list of IO redirections for the child
\return 0 on sucess, -1 on failiure
*/
static int handle_child_io(const io_chain_t &io_chain)
{
for (size_t idx = 0; idx < io_chain.size(); idx++)
{
const io_data_t *io = io_chain.at(idx).get();
int tmp;
if (io->io_mode == IO_FD && io->fd == static_cast<const io_fd_t*>(io)->old_fd)
{
continue;
}
switch (io->io_mode)
{
case IO_CLOSE:
{
if (log_redirections) fprintf(stderr, "%d: close %d\n", getpid(), io->fd);
if (close(io->fd))
{
debug_safe_int(0, "Failed to close file descriptor %s", io->fd);
safe_perror("close");
}
break;
}
case IO_FILE:
{
// Here we definitely do not want to set CLO_EXEC because our child needs access
CAST_INIT(const io_file_t *, io_file, io);
if ((tmp=open(io_file->filename_cstr,
io_file->flags, OPEN_MASK))==-1)
{
if ((io_file->flags & O_EXCL) &&
(errno ==EEXIST))
{
debug_safe(1, NOCLOB_ERROR, io_file->filename_cstr);
}
else
{
debug_safe(1, FILE_ERROR, io_file->filename_cstr);
safe_perror("open");
}
return -1;
}
else if (tmp != io->fd)
{
/*
This call will sometimes fail, but that is ok,
this is just a precausion.
*/
close(io->fd);
if (dup2(tmp, io->fd) == -1)
{
debug_safe_int(1, FD_ERROR, io->fd);
safe_perror("dup2");
return -1;
}
exec_close(tmp);
}
break;
}
case IO_FD:
{
int old_fd = static_cast<const io_fd_t *>(io)->old_fd;
if (log_redirections) fprintf(stderr, "%d: fd dup %d to %d\n", getpid(), old_fd, io->fd);
/*
This call will sometimes fail, but that is ok,
this is just a precausion.
*/
close(io->fd);
if (dup2(old_fd, io->fd) == -1)
{
debug_safe_int(1, FD_ERROR, io->fd);
safe_perror("dup2");
return -1;
}
break;
}
case IO_BUFFER:
case IO_PIPE:
{
//.........这里部分代码省略.........
示例13: io_transmogrify
/// Make a copy of the specified io redirection chain, but change file redirection into fd
/// redirection. This makes the redirection chain suitable for use as block-level io, since the file
/// won't be repeatedly reopened for every command in the block, which would reset the cursor
/// position.
///
/// \return true on success, false on failure. Returns the output chain and opened_fds by reference.
static bool io_transmogrify(const io_chain_t &in_chain, io_chain_t *out_chain,
std::vector<int> *out_opened_fds) {
ASSERT_IS_MAIN_THREAD();
assert(out_chain != NULL && out_opened_fds != NULL);
assert(out_chain->empty());
// Just to be clear what we do for an empty chain.
if (in_chain.empty()) {
return true;
}
bool success = true;
// Make our chain of redirections.
io_chain_t result_chain;
// In the event we can't finish transmorgrifying, we'll have to close all the files we opened.
std::vector<int> opened_fds;
for (size_t idx = 0; idx < in_chain.size(); idx++) {
const shared_ptr<io_data_t> &in = in_chain.at(idx);
shared_ptr<io_data_t> out; // gets allocated via new
switch (in->io_mode) {
case IO_PIPE:
case IO_FD:
case IO_BUFFER:
case IO_CLOSE: {
// These redirections don't need transmogrification. They can be passed through.
out = in;
break;
}
case IO_FILE: {
// Transmogrify file redirections.
int fd;
io_file_t *in_file = static_cast<io_file_t *>(in.get());
if ((fd = open(in_file->filename_cstr, in_file->flags, OPEN_MASK)) == -1) {
debug(1, FILE_ERROR, in_file->filename_cstr);
wperror(L"open");
success = false;
break;
}
opened_fds.push_back(fd);
out.reset(new io_fd_t(in->fd, fd, false));
break;
}
}
if (out.get() != NULL) result_chain.push_back(out);
// Don't go any further if we failed.
if (!success) {
break;
}
}
// Now either return success, or clean up.
if (success) {
*out_chain = std::move(result_chain);
*out_opened_fds = std::move(opened_fds);
} else {
result_chain.clear();
io_cleanup_fds(opened_fds);
}
return success;
}
示例14: io_remove
void io_remove(io_chain_t &list, const shared_ptr<const io_data_t> &element)
{
list.remove(element);
}
示例15: append
void io_chain_t::append(const io_chain_t &chain)
{
this->insert(this->end(), chain.begin(), chain.end());
}