📄 io.c
字号:
/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA *//** * @file * * Common low-level IO utilities. * * This code is not meant to know about our protocol, only to provide * a more comfortable layer on top of Unix IO. * * @todo Perhaps write things out using writev() to reduce the number * of system calls, and the risk of small packets when not using * TCP_CORK. */#include "config.h"#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <errno.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/socket.h>#ifdef HAVE_SYS_SELECT_H# include <sys/select.h>#endif#include <sys/time.h>#include <netinet/in.h>#include <netinet/tcp.h>#include "distcc.h"#include "trace.h"#include "util.h"#include "exitcode.h"/** Timeout for all IO other than opening connections. Much longer, because * compiling files can take a long time. **/const int dcc_io_timeout = 300; /* seconds *//** * @todo Perhaps only apply the timeout for initial connections, not when * doing regular IO. **/int dcc_select_for_read(int fd, int timeout){ fd_set fds; int rs; struct timeval tv; tv.tv_sec = timeout; tv.tv_usec = 0; while (1) { FD_ZERO(&fds); FD_SET(fd, &fds); /* Linux updates the timeval to reflect the remaining time, but other * OSs may not. So on other systems, we may wait a bit too long if * the client is interrupted -- but that won't happen very often so * it's no big deal. */ rs_trace("select for read on fd%d for %ds", fd, (int) tv.tv_sec); rs = select(fd+1, &fds, NULL, NULL, &tv); if (rs == -1 && errno == EINTR) { rs_trace("select was interrupted"); continue; } else if (rs == -1) { rs_log_error("select() failed: %s", strerror(errno)); return EXIT_IO_ERROR; } else if (rs == 0) { rs_log_error("IO timeout"); return EXIT_IO_ERROR; } else if (!FD_ISSET(fd, &fds)) { rs_log_error("how did fd not get set?"); continue; } else { break; /* woot */ } } return 0;}int dcc_select_for_write(int fd, int timeout){ fd_set fds; int rs; struct timeval tv; tv.tv_sec = timeout; tv.tv_usec = 0; while (1) { FD_ZERO(&fds); FD_SET(fd, &fds); rs_trace("select for write on fd%d", fd); rs = select(fd + 1, NULL, &fds, &fds, &tv); if (rs == -1 && errno == EINTR) { rs_trace("select was interrupted"); continue; } else if (rs == -1) { rs_log_error("select failed: %s", strerror(errno)); return EXIT_IO_ERROR; } else { return 0; } }}/** * Read exactly @p len bytes from a file. **/int dcc_readx(int fd, void *buf, size_t len){ ssize_t r; int ret; while (len > 0) { r = read(fd, buf, len); if (r == -1 && errno == EAGAIN) { if ((ret = dcc_select_for_read(fd, dcc_io_timeout))) return ret; else continue; } else if (r == -1 && errno == EAGAIN) { continue; } else if (r == -1) { rs_log_error("failed to read: %s", strerror(errno)); return EXIT_IO_ERROR; } else if (r == 0) { rs_log_error("unexpected eof on fd%d", fd); return EXIT_TRUNCATED; } else { buf = &((char *) buf)[r]; len -= r; } } return 0;}/** * Write bytes to an fd. Keep writing until we're all done or something goes * wrong. * * @returns 0 or exit code. **/int dcc_writex(int fd, const void *buf, size_t len){ ssize_t r; int ret; while (len > 0) { r = write(fd, buf, len); if (r == -1 && errno == EAGAIN) { if ((ret = dcc_select_for_write(fd, dcc_io_timeout))) return ret; else continue; } else if (r == -1 && errno == EINTR) { continue; } else if (r == -1) { rs_log_error("failed to write: %s", strerror(errno)); return EXIT_IO_ERROR; } else if (r == 0) { rs_log_error("unexpected eof on fd%d", fd); return EXIT_TRUNCATED; } else { buf = &((char *) buf)[r]; len -= r; } } return 0;}/** * Stick a TCP cork in the socket. It's not clear that this will help * performance, but it might. * * This is a no-op if we don't think this platform has corks. **/int tcp_cork_sock(int fd, int corked){#ifdef TCP_CORK if (!dcc_getenv_bool("DISTCC_TCP_CORK", 1)) return 0; if (setsockopt(fd, SOL_TCP, TCP_CORK, &corked, sizeof corked) == -1) { if (errno == ENOSYS || errno == ENOTSUP) { if (corked) rs_trace("no corks allowed on fd%d", fd); /* no need to complain about not uncorking */ } else { rs_log_warning("setsockopt(corked=%d) failed: %s", corked, strerror(errno)); /* continue anyhow */ } }#endif /* def TCP_CORK */ return 0;}int dcc_close(int fd){ if (close(fd) != 0) { rs_log_error("failed to close fd%d: %s", fd, strerror(errno)); return EXIT_IO_ERROR; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -