From mboxrd@z Thu Jan 1 00:00:00 1970 From: rmccabe@sourceware.org Date: 30 Aug 2007 22:50:14 -0000 Subject: [Cluster-devel] conga/ricci/common ClientSocket.cpp Except.cpp ... Message-ID: <20070830225014.797.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit CVSROOT: /cvs/cluster Module name: conga Changes by: rmccabe at sourceware.org 2007-08-30 22:50:14 Modified files: ricci/common : ClientSocket.cpp Except.cpp File.cpp Socket.cpp executils.cpp Log message: - More cleanup - Better error messages Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/ClientSocket.cpp.diff?cvsroot=cluster&r1=1.8&r2=1.9 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/Except.cpp.diff?cvsroot=cluster&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/File.cpp.diff?cvsroot=cluster&r1=1.4&r2=1.5 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/Socket.cpp.diff?cvsroot=cluster&r1=1.7&r2=1.8 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/executils.cpp.diff?cvsroot=cluster&r1=1.9&r2=1.10 --- conga/ricci/common/ClientSocket.cpp 2007/06/25 16:03:42 1.8 +++ conga/ricci/common/ClientSocket.cpp 2007/08/30 22:50:13 1.9 @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* @@ -35,200 +35,214 @@ #include - ClientSocket::ClientSocket() : - Socket(-1) + Socket(-1) {} ClientSocket::ClientSocket(int sock, u_int32_t addr) : - Socket(sock), - _addr(addr) + Socket(sock), + _addr(addr) {} ClientSocket::ClientSocket(const String& sock_path) : - Socket(-1) + Socket(-1) { - _sock = socket(PF_UNIX, SOCK_STREAM, 0); - if (_sock == -1) - throw String("ClientSocket(String): socket() failed"); - - struct sockaddr_un { - sa_family_t sun_family; - char sun_path[100]; - } addr; - addr.sun_family = AF_UNIX; - memcpy(addr.sun_path, sock_path.c_str(), sock_path.size()+1); - - if (connect(_sock, (struct sockaddr*) &addr, sizeof(addr))) { - throw String("ClientSocket(String): connect() failed"); - } - - // String msg = String("created client socket ") + _sock; - // msg += ", and connected to " + sock_path; - // log(msg, LogSocket); -} - -ClientSocket::ClientSocket(const String& hostname, - unsigned short port, - unsigned int timeout_ms) : - Socket(-1) -{ - _sock = socket(PF_INET, SOCK_STREAM, 0); - if (_sock == -1) - throw String("ClientSocket(hostname, port, timeout): socket() failed"); - - if (timeout_ms) - nonblocking(true); - - counting_auto_ptr ent = Network::getHostByName(hostname); - - char** addrs = (*ent)->h_addr_list; - for (int i=0; addrs[i]; i++) { - struct sockaddr_in addr_in; - addr_in.sin_family = AF_INET; - addr_in.sin_port = htons(port); - addr_in.sin_addr.s_addr = *((u_int32_t*) addrs[i]); - - if (connect(_sock, (struct sockaddr*) &addr_in, sizeof(addr_in)) == 0) { - // connected - nonblocking(false); - _addr = addr_in.sin_addr.s_addr; - return; - } - - // connect() error - if (errno != EINPROGRESS) - continue; - bool can_read=false, can_write=true; - poll(can_read, can_write, timeout_ms); - if (can_write == false) { - // connect() not completed - throw String("ClientSocket(hostname, port, timeout): connect() timed out"); - } - // connect() completed, check successfulness - int err = 1; - socklen_t err_size = sizeof(err); - getsockopt(_sock, SOL_SOCKET, SO_ERROR, - &err, &err_size); - if (err) - continue; - - // connected - nonblocking(false); - _addr = addr_in.sin_addr.s_addr; - return; - } - throw String("ClientSocket(hostname, port, timeout): connect() failed"); + _sock = socket(PF_UNIX, SOCK_STREAM, 0); + if (_sock == -1) { + throw String("ClientSocket(String): socket() failed: ") + + String(strerror(errno)); + } + + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + if (sock_path.size() >= sizeof(addr.sun_path)) + throw String("path to client unix socket is too long"); + memcpy(addr.sun_path, sock_path.c_str(), sock_path.size()+1); + + if (connect(_sock, (struct sockaddr*) &addr, sizeof(addr))) { + throw String("ClientSocket(String): connect() failed: ") + + String(strerror(errno)); + } + + //String msg = String("created client socket ") + _sock; + //msg += ", and connected to " + sock_path; + //log(msg, LogSocket); +} + +ClientSocket::ClientSocket( const String& hostname, + unsigned short port, + unsigned int timeout_ms) : + Socket(-1) +{ + _sock = socket(PF_INET, SOCK_STREAM, 0); + if (_sock == -1) { + throw String("ClientSocket(hostname, port, timeout): socket() failed") + + String(strerror(errno)); + } + + if (timeout_ms) + nonblocking(true); + + counting_auto_ptr ent = Network::getHostByName(hostname); + + char **addrs = (*ent)->h_addr_list; + for (int i = 0 ; addrs[i] ; i++) { + struct sockaddr_in addr_in; + + addr_in.sin_family = AF_INET; + addr_in.sin_port = htons(port); + addr_in.sin_addr.s_addr = *((u_int32_t*) addrs[i]); + + if (connect(_sock, (struct sockaddr *) &addr_in, sizeof(addr_in)) == 0) + { + // connected + nonblocking(false); + _addr = addr_in.sin_addr.s_addr; + return; + } + + // connect() error + if (errno != EINPROGRESS) + continue; + + bool can_read = false, can_write = true; + poll(can_read, can_write, timeout_ms); + + if (can_write == false) { + // connect() not completed + throw String("ClientSocket(hostname, port, timeout): connect() timed out") + String(strerror(errno)); + } + + // connect() completed, check successfulness + int err = 1; + socklen_t err_size = sizeof(err); + getsockopt(_sock, SOL_SOCKET, SO_ERROR, &err, &err_size); + + if (err) + continue; + + // connected + nonblocking(false); + _addr = addr_in.sin_addr.s_addr; + return; + } + + throw String("ClientSocket(hostname, port, timeout): connect() failed"); } ClientSocket::ClientSocket(const ClientSocket& s) : - Socket(s), - _addr(s._addr) + Socket(s), + _addr(s._addr) {} -ClientSocket& +ClientSocket& ClientSocket::operator= (const ClientSocket& s) { - if (&s != this) { - this->Socket::operator= (s); - _addr = s._addr; - } - return *this; + if (&s != this) { + this->Socket::operator= (s); + _addr = s._addr; + } + return *this; } ClientSocket::~ClientSocket() {} - -bool +bool ClientSocket::connected_to(const String& hostname) { - try { - counting_auto_ptr ent = Network::getHostByName(hostname); - char** addrs = (*ent)->h_addr_list; - for (int i=0; addrs[i]; i++) - if (*((u_int32_t*) addrs[i]) == _addr) - return true; - } catch ( ... ) {} - return false; + try { + counting_auto_ptr ent = Network::getHostByName(hostname); + char **addrs = (*ent)->h_addr_list; + for (int i = 0 ; addrs[i] ; i++) { + if (*((u_int32_t *) addrs[i]) == _addr) + return true; + } + } catch ( ... ) {} + + return false; } -String +String ClientSocket::recv() { - if (_sock == -1) - throw String("ClientSocket::recv(): socket already closed"); - - while (true) { - char buffer[4096]; - int ret = ::recv(_sock, buffer, sizeof(buffer), 0); - if (ret == -1) { - if (errno == EINTR) - continue; - else if (errno == EAGAIN) - return ""; - throw String("ClientSocket::recv(): recv error: ") + String(strerror(errno)); - } - - if (ret == 0) { - close(); - throw String("ClientSocket::recv(): socket has been shutdown"); - } - - // log(String("received ") + ret + " bytes from socket " + _sock, - // LogLevel(LogSocket|LogTransfer)); - String data(buffer, ret); - shred(buffer, ret); - return data; - } + if (_sock == -1) + throw String("ClientSocket::recv(): socket already closed"); + + while (true) { + char buffer[4096]; + int ret = ::recv(_sock, buffer, sizeof(buffer), 0); + if (ret == -1) { + if (errno == EINTR) + continue; + else if (errno == EAGAIN) + return ""; + throw String("ClientSocket::recv(): recv error: ") + + String(strerror(errno)); + } + + if (ret == 0) { + close(); + throw String("ClientSocket::recv(): socket has been shutdown"); + } + + //log(String("received ") + ret + " bytes from socket " + _sock, + //LogLevel(LogSocket|LogTransfer)); + String data(buffer, ret); + shred(buffer, ret); + return data; + } } String ClientSocket::recv(int timeout) { - bool in=true, out=false; - poll(in, out, timeout); - if (in) - return recv(); - else - return ""; + bool in = true, out = false; + + poll(in, out, timeout); + if (in) + return recv(); + else + return ""; } -String +String ClientSocket::send(const String& msg) { - if (_sock == -1) - throw String("ClientSocket::send(): socket already closed"); - - while (true) { - int ret = ::send(_sock, msg.c_str(), msg.size(), 0); - if (ret == -1) { - if (errno == EINTR) - continue; - else if (errno == EAGAIN || errno == EWOULDBLOCK) - return msg; - throw String("ClientSocket::send(): socket error: ") + String(strerror(errno)); - } - - // log(String("sent ") + ret + " bytes thru socket " + _sock, - // LogLevel(LogSocket|LogTransfer)); - return msg.substr(ret); - } + if (_sock == -1) + throw String("ClientSocket::send(): socket already closed"); + + while (true) { + int ret = ::send(_sock, msg.c_str(), msg.size(), 0); + if (ret == -1) { + if (errno == EINTR) + continue; + else if (errno == EAGAIN || errno == EWOULDBLOCK) + return msg; + throw String("ClientSocket::send(): socket error: ") + + String(strerror(errno)); + } + + //log(String("sent ") + ret + " bytes thru socket " + _sock, + //LogLevel(LogSocket|LogTransfer)); + return msg.substr(ret); + } } String ClientSocket::send(const String& msg, int timeout) { - bool in=false, out=true; - poll(in, out, timeout); - if (out) - return send(msg); - else - return msg; + bool in = false, out = true; + + poll(in, out, timeout); + if (out) + return send(msg); + else + return msg; } -void +void ClientSocket::ready(bool& recv, bool& send, int timeout) { - poll(recv, send, timeout); + poll(recv, send, timeout); } --- conga/ricci/common/Except.cpp 2006/08/10 22:53:07 1.2 +++ conga/ricci/common/Except.cpp 2007/08/30 22:50:13 1.3 @@ -1,5 +1,5 @@ /* - Copyright Red Hat, Inc. 2005 + Copyright Red Hat, Inc. 2005-2007 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 @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* @@ -27,26 +27,24 @@ using namespace std; - -Except::Except(long long error_code, - const String& msg) : - _code(error_code), _msg(msg) +Except::Except(long long error_code, const String& msg) : + _code(error_code), _msg(msg) { - if (_code == generic_error) - throw String("Exception() invalid error_code"); + if (_code == generic_error) + throw String("Exception() invalid error_code"); } Except::~Except() {} -long long +long long Except::code() const { - return _code; + return _code; } -String +String Except::description() const { - return _msg; + return _msg; } --- conga/ricci/common/File.cpp 2007/08/24 22:05:13 1.4 +++ conga/ricci/common/File.cpp 2007/08/30 22:50:13 1.5 @@ -1,5 +1,5 @@ /* - Copyright Red Hat, Inc. 2006 + Copyright Red Hat, Inc. 2006-2007 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 @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* @@ -29,194 +29,197 @@ using namespace std; -File_pimpl::File_pimpl(void* fs, - bool& owner) : - fs(fs) -{ - if (fs == 0) - throw String("fs_ptr is null!!!"); - owner = true; +File_pimpl::File_pimpl(void *fs, bool& owner) : + fs(fs) +{ + if (fs == NULL) + throw String("fs_ptr is null"); + owner = true; } File_pimpl::~File_pimpl() { - fstream* ptr = (fstream*) fs; - delete ptr; + fstream *ptr = (fstream *) fs; + delete ptr; } +File +File::open(const String& filepath, bool rw) +{ + if (access(filepath.c_str(), R_OK)) + throw String("unable to read file ") + filepath; + ios_base::openmode mode = ios_base::in; + if (rw) + mode |= ios_base::out; + + counting_auto_ptr pimpl; + bool ownership_taken = false; + fstream *fs = new fstream(filepath.c_str(), mode); + try { + pimpl = counting_auto_ptr(new File_pimpl(fs, ownership_taken)); + } catch ( ... ) { + if (!ownership_taken) + delete fs; + throw; + } + return File(pimpl, filepath, rw); +} File -File::open(const String& filepath, - bool rw) +File::create(const String& filepath, bool truncate) { - if (access(filepath.c_str(), R_OK)) - throw String("unable to read file ") + filepath; - ios_base::openmode mode = ios_base::in; - if (rw) - mode |= ios_base::out; - - counting_auto_ptr pimpl; - bool ownership_taken = false; - fstream* fs = new fstream(filepath.c_str(), mode); - try { - pimpl = counting_auto_ptr(new File_pimpl(fs, ownership_taken)); - } catch ( ... ) { - if (!ownership_taken) - delete fs; - throw; - } - return File(pimpl, filepath, rw); -} - -File -File::create(const String& filepath, - bool truncate) -{ - int t = ::open(filepath.c_str(), - O_CREAT|O_RDWR, - S_IRUSR|S_IWUSR|S_IRGRP); - if (t != -1) - while (close(t) && errno == EINTR) - ; - - ios_base::openmode mode = ios_base::in; - mode |= ios_base::out; - if (truncate) - mode |= ios_base::trunc; - - counting_auto_ptr pimpl; - bool ownership_taken = false; - fstream* fs = new fstream(filepath.c_str(), mode); - try { - pimpl = counting_auto_ptr(new File_pimpl(fs, ownership_taken)); - } catch ( ... ) { - if (!ownership_taken) - delete fs; - throw; - } - return File(pimpl, filepath, true); -} - -File::File(counting_auto_ptr pimpl, - const String& path, - bool writable) : - _mutex(counting_auto_ptr(new Mutex())), - _pimpl(pimpl), - _path(path), - _writable(writable) -{ - if (!((fstream*) _pimpl->fs)->is_open()) - throw String("unable to open ") + _path; - check_failed(); + int t = ::open(filepath.c_str(), O_CREAT | O_RDWR, 0640); + if (t != -1) { + while (close(t) && errno == EINTR) + ; + } + + ios_base::openmode mode = ios_base::in; + mode |= ios_base::out; + if (truncate) + mode |= ios_base::trunc; + + counting_auto_ptr pimpl; + bool ownership_taken = false; + fstream *fs = new fstream(filepath.c_str(), mode); + + try { + pimpl = counting_auto_ptr(new File_pimpl(fs, ownership_taken)); + } catch ( ... ) { + if (!ownership_taken) + delete fs; + throw; + } + return File(pimpl, filepath, true); +} + +File::File( counting_auto_ptr pimpl, + const String& path, + bool writable) : + _mutex(counting_auto_ptr(new Mutex())), + _pimpl(pimpl), + _path(path), + _writable(writable) +{ + if (!((fstream *) _pimpl->fs)->is_open()) + throw String("unable to open ") + _path; + check_failed(); } File::~File() { - if (_writable) - ((fstream*) _pimpl->fs)->flush(); + if (_writable) + ((fstream*) _pimpl->fs)->flush(); } -String +String File::path() const { - MutexLocker l(*_mutex); - - return _path; + MutexLocker l(*_mutex); + return _path; } -long +long File::size() const { - MutexLocker l(*_mutex); - ((fstream*) _pimpl->fs)->seekg(0, ios::end); - check_failed(); - long s = ((fstream*) _pimpl->fs)->tellg(); - check_failed(); - if (s < 0) - throw String("size of file ") + _path + " is negative!!!"; - return s; + MutexLocker l(*_mutex); + ((fstream *) _pimpl->fs)->seekg(0, ios::end); + check_failed(); + + long s = ((fstream *) _pimpl->fs)->tellg(); + check_failed(); + + if (s < 0) + throw String("size of file ") + _path + " is negative"; + return s; } -String +String File::read() const { - MutexLocker l(*_mutex); - - long len = size(); - const auto_ptr buff(new char[len]); - try { - ((fstream*) _pimpl->fs)->seekg(0, ios::beg); - check_failed(); - ((fstream*) _pimpl->fs)->read(buff.get(), len); - check_failed(); - String ret(buff.get(), len); - ::shred(buff.get(), len); - return ret; - } catch ( ... ) { - ::shred(buff.get(), len); - throw; - } + MutexLocker l(*_mutex); + + long len = size(); + const auto_ptr buff(new char[len]); + try { + ((fstream *) _pimpl->fs)->seekg(0, ios::beg); + check_failed(); + ((fstream *) _pimpl->fs)->read(buff.get(), len); + check_failed(); + String ret(buff.get(), len); + ::shred(buff.get(), len); + return ret; + } catch ( ... ) { + ::shred(buff.get(), len); + throw; + } } -File& +File& File::append(const String& data) { - MutexLocker l(*_mutex); - if (!_writable) - throw String("not writable"); - ((fstream*) _pimpl->fs)->seekp(0, ios::end); - check_failed(); - ((fstream*) _pimpl->fs)->write(data.c_str(), data.size()); - check_failed(); - ((fstream*) _pimpl->fs)->flush(); - check_failed(); - return *this; + MutexLocker l(*_mutex); + if (!_writable) + throw String("not writable"); + + ((fstream *) _pimpl->fs)->seekp(0, ios::end); + check_failed(); + + ((fstream *) _pimpl->fs)->write(data.c_str(), data.size()); + check_failed(); + + ((fstream *) _pimpl->fs)->flush(); + check_failed(); + return *this; } -String +String File::replace(const String& data) { - MutexLocker l(*_mutex); - if (!_writable) - throw String("not writable"); - String old(read()); - create(_path, true); - append(data); - return old; + MutexLocker l(*_mutex); + if (!_writable) + throw String("not writable"); + + String old(read()); + create(_path, true); + append(data); + return old; } -void +void File::shred() { - MutexLocker l(*_mutex); - if (!_writable) - throw String("not writable"); - unsigned int len = size(); - ((fstream*) _pimpl->fs)->seekp(0, ios::beg); - check_failed(); - // should use random source (paranoid) - // doesn't work on journaled fss anyways - ((fstream*) _pimpl->fs)->write(String(len, 'o').c_str(), len); - check_failed(); + MutexLocker l(*_mutex); + if (!_writable) + throw String("not writable"); + + unsigned int len = size(); + ((fstream *) _pimpl->fs)->seekp(0, ios::beg); + check_failed(); + + // should use random source (paranoid) + // doesn't work on journaled fss anyways + ((fstream *) _pimpl->fs)->write(String(len, 'o').c_str(), len); + check_failed(); } -void +void File::unlink() { - MutexLocker l(*_mutex); - if (::unlink(_path.c_str())) - throw String("unlink failed: " + String(strerror(errno))); + MutexLocker l(*_mutex); + if (::unlink(_path.c_str())) + throw String("unlink failed: " + String(strerror(errno))); } File::operator const String () const { - return read(); + return read(); } void File::check_failed() const { - if (((fstream*) _pimpl->fs)->fail()) - throw String("IO error"); + if (((fstream *) _pimpl->fs)->fail()) + throw String("IO error"); } --- conga/ricci/common/Socket.cpp 2007/08/24 22:05:14 1.7 +++ conga/ricci/common/Socket.cpp 2007/08/30 22:50:13 1.8 @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* @@ -35,147 +35,152 @@ #include #include -typedef struct pollfd poll_fd; - +typedef struct pollfd poll_fd; -Socket::Socket(int sock) : - _sock(sock) +Socket::Socket(int sock) : + _sock(sock) { - try { - _counter = counting_auto_ptr(new int(1)); - } catch ( ... ) { - close(); - throw String("Socket(int sock) failed"); - } + try { + _counter = counting_auto_ptr(new int(1)); + } catch ( ... ) { + close(); + throw String("Socket(int sock) failed"); + } } Socket::Socket(const Socket& s) : - _sock(s._sock), - _counter(s._counter) + _sock(s._sock), + _counter(s._counter) { - (*_counter)++; + (*_counter)++; } -Socket& +Socket& Socket::operator= (const Socket& s) { - if (&s != this) { - decrease_counter(); - _sock = s._sock; - _counter = s._counter; - (*_counter)++; - } - return *this; + if (&s != this) { + decrease_counter(); + _sock = s._sock; + _counter = s._counter; + (*_counter)++; + } + + return *this; } Socket::~Socket() { - decrease_counter(); + decrease_counter(); } -void +void Socket::decrease_counter() { - if (--(*_counter) == 0) - close(); + if (--(*_counter) == 0) + close(); } - + void Socket::close() { - if (_sock != -1) { - log(String("closing socket ") + _sock, LogSocket); - shutdown(_sock, SHUT_RDWR); - int e; - do { - e = ::close(_sock); - } while (e && (errno == EINTR)); - } - _sock = -1; + if (_sock != -1) { + log(String("closing socket ") + _sock, LogSocket); + shutdown(_sock, SHUT_RDWR); + + int e; + do { + e = ::close(_sock); + } while (e && (errno == EINTR)); + } + _sock = -1; } - -bool +bool Socket::operator== (const Socket& obj) { - return obj._sock == _sock; + return obj._sock == _sock; } -int +int Socket::get_sock() { - return _sock; + return _sock; } -bool +bool Socket::nonblocking() { - if (!valid()) - throw String("socket not valid"); - int flags = fcntl(_sock, F_GETFL); - if (flags == -1) - throw String("fcntl(F_GETFL): " + String(strerror(errno))); - return flags & O_NONBLOCK; + if (!valid()) + throw String("socket not valid"); + + int flags = fcntl(_sock, F_GETFL); + if (flags == -1) + throw String("fcntl(F_GETFL): " + String(strerror(errno))); + return (flags & O_NONBLOCK) != 0; } -bool +bool Socket::nonblocking(bool mode) { - if (!valid()) - throw String("socket not valid"); - int old_flags = fcntl(_sock, F_GETFL); - if (old_flags == -1) - throw String("fcntl(F_GETFL): " + String(strerror(errno))); - int new_flags; - if (mode) - new_flags = old_flags | O_NONBLOCK; - else - new_flags = old_flags & ~O_NONBLOCK; - if (fcntl(_sock, F_SETFL, new_flags)) - throw String("fcntl(F_SETFL): " + String(strerror(errno))); - return old_flags & O_NONBLOCK; + if (!valid()) + throw String("socket not valid"); + + int old_flags = fcntl(_sock, F_GETFL); + if (old_flags == -1) + throw String("fcntl(F_GETFL): " + String(strerror(errno))); + + int new_flags; + if (mode) + new_flags = old_flags | O_NONBLOCK; + else + new_flags = old_flags & ~O_NONBLOCK; + + if (fcntl(_sock, F_SETFL, new_flags)) + throw String("fcntl(F_SETFL): " + String(strerror(errno))); + return (old_flags & O_NONBLOCK) != 0; } void Socket::poll(bool& read, bool& write, int timeout) { - if (!valid()) - throw String("socket not valid"); - - poll_fd poll_data; - poll_data.fd = _sock; - poll_data.events = (read ? POLLIN : 0) | (write ? POLLOUT : 0); - - read = write = false; - int beg = time_mil(); - - while ( true ) { - int time2wait; - if (timeout <= 0) - time2wait = timeout; - else { - time2wait = beg + timeout - time_mil(); - if (time2wait < 0) - return; - } - poll_data.revents = 0; - int ret = ::poll(&poll_data, 1, time2wait); - if (ret == 0) - return; - else if (ret == -1) { - if (errno == EINTR) - continue; - else - throw String("poll() error: " + String(strerror(errno))); - } else { - if (poll_data.revents & POLLIN) - read = true; - if (poll_data.revents & POLLOUT) - write = true; - if (poll_data.revents & (POLLERR | POLLHUP | POLLNVAL)) - read = write = true; - return; - } - } + if (!valid()) + throw String("socket not valid"); + + poll_fd poll_data; + poll_data.fd = _sock; + poll_data.events = (read ? POLLIN : 0) | (write ? POLLOUT : 0); + + read = write = false; + int beg = time_mil(); + + while (true) { + int time2wait; + if (timeout <= 0) + time2wait = timeout; + else { + time2wait = beg + timeout - time_mil(); + if (time2wait < 0) + return; + } + poll_data.revents = 0; + + int ret = ::poll(&poll_data, 1, time2wait); + if (ret == 0) + return; + else if (ret == -1) { + if (errno == EINTR) + continue; + else + throw String("poll() error: " + String(strerror(errno))); + } else { + if (poll_data.revents & POLLIN) + read = true; + if (poll_data.revents & POLLOUT) + write = true; + if (poll_data.revents & (POLLERR | POLLHUP | POLLNVAL)) + read = write = true; + return; + } + } } --- conga/ricci/common/executils.cpp 2007/06/25 16:03:42 1.9 +++ conga/ricci/common/executils.cpp 2007/08/30 22:50:13 1.10 @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* @@ -36,223 +36,223 @@ -static void -read_data(struct pollfd& poll_info, - bool& fd_closed, - String& data); -static void -close_fd(int fd); +static void read_data(struct pollfd& poll_info, bool& fd_closed, String& data); +static void close_fd(int fd); - -int -execute(const String& path, - const std::vector& args, - String& out, - String& err, - int& status, - int timeout) +int +execute(const String& path, + const std::vector& args, + String& out, + String& err, + int& status, + int timeout) { - if (access(path.c_str(), X_OK)) - return 1; - - out = err = ""; - - int _stdout_pipe[2]; - int _stderr_pipe[2]; - if (pipe(_stdout_pipe) == -1) - return 2; - if (pipe(_stderr_pipe) == -1) { - close_fd(_stdout_pipe[0]); - close_fd(_stdout_pipe[1]); - return 2; - } - - int pid = fork(); - if (pid == -1) { - close_fd(_stdout_pipe[0]); - close_fd(_stdout_pipe[1]); - close_fd(_stderr_pipe[0]); - close_fd(_stderr_pipe[1]); - return 3; - } - - unsigned int time_beg = time_mil(); - unsigned int time_to_kill = time_beg + timeout; - - if (pid == 0) { - /* child */ - - close_fd(1); - close_fd(_stdout_pipe[0]); - dup2(_stdout_pipe[1], 1); - close_fd(_stdout_pipe[1]); - - close_fd(2); - close_fd(_stderr_pipe[0]); - dup2(_stderr_pipe[1], 2); - close_fd(_stderr_pipe[1]); - - int devnull = open("/dev/null", O_RDWR); - if (devnull == -1) { - perror("ricci::execute(): Can't open /dev/null"); - _exit(1); - } - close_fd(0); - dup2(devnull, 0); - close_fd(devnull); - - // close open fds - for (unsigned int i=3; i<__FD_SETSIZE; i++) - close_fd(i); - - // restore signals - for (int x = 1; x < _NSIG; x++) - signal(x, SIG_DFL); - sigset_t set; - sigfillset(&set); - sigprocmask(SIG_UNBLOCK, &set, NULL); - - setenv("LANG", "C", 1); - setenv("LC_ALL", "C", 1); - - /* exec */ - - try { - unsigned int size = args.size() + 2; - char** argv = new char*[size]; - argv[0] = (char*) path.c_str(); - for (unsigned int i=0; i= 0 && - time_mil() > time_to_kill) - kill(pid, SIGKILL); - - // prepare poll structs - struct pollfd poll_data[2]; - int s = 0; - if (!out_closed) { - poll_data[s].fd = _stdout_pipe[0]; - poll_data[s].events = POLLIN; - poll_data[s].revents = 0; - s += 1; - } - if (!err_closed) { - poll_data[s].fd = _stderr_pipe[0]; - poll_data[s].events = POLLIN; - poll_data[s].revents = 0; - s += 1; - } - if (s == 0) - break; - - // wait for events - int ret = poll(poll_data, s, 500); - if (ret == 0) - continue; - else if (ret == -1) { - if (errno == EINTR) - continue; - else { - if (!out_closed) - close_fd(_stdout_pipe[0]); - if (!err_closed) - close_fd(_stderr_pipe[0]); - return 4; - } - } - - // process events - for (int i=0; i= 0 && time_mil() > time_to_kill) { + kill(pid, SIGTERM); + sleep(1); + kill(pid, SIGKILL); + } + + // prepare poll structs + struct pollfd poll_data[2]; + int s = 0; + if (!out_closed) { + poll_data[s].fd = _stdout_pipe[0]; + poll_data[s].events = POLLIN; + poll_data[s].revents = 0; + s += 1; + } + + if (!err_closed) { + poll_data[s].fd = _stderr_pipe[0]; + poll_data[s].events = POLLIN; + poll_data[s].revents = 0; + s += 1; + } + + if (s == 0) + break; + + // wait for events + int ret = poll(poll_data, s, 500); + if (ret == 0) + continue; + else if (ret == -1) { + if (errno == EINTR) + continue; + else { + if (!out_closed) + close_fd(_stdout_pipe[0]); + if (!err_closed) + close_fd(_stderr_pipe[0]); + return 4; + } + } + + // process events + for (int i = 0 ; i < s ; i++) { + struct pollfd& poll_info = poll_data[i]; + + if (poll_info.fd == _stdout_pipe[0]) + read_data(poll_info, out_closed, out); + if (poll_info.fd == _stderr_pipe[0]) + read_data(poll_info, err_closed, err); + } + } // while (true) + + // command + String comm(path); + for (unsigned int i = 0 ; i < args.size() ; i++) + comm += " " + args[i]; + + // get status + int ret; + do { + ret = waitpid(pid, &status, 0); + } while ((ret < 0) && (errno == EINTR)); + + if (WIFEXITED(status)) { + //log("executed \"" + comm + "\" in " + (time_mil() - time_beg) + " milliseconds", LogExecute); + status = WEXITSTATUS(status); + return 0; + } else if (WIFSIGNALED(status)) { + //log("\"" + comm + "\" killed after " + (time_mil() - time_beg) + " milliseconds", LogExecute); + return 5; + } else { + //log("unknown cause of \"" + comm + "\"'s exit after " + (time_mil() - time_beg) + " milliseconds", LogExecute); + return 6; + } } -void -read_data(struct pollfd& poll_info, - bool& fd_closed, - String& data) +void +read_data(struct pollfd& poll_info, bool& fd_closed, String& data) { - int fd = poll_info.fd; - - if (poll_info.revents & POLLIN) { - try { - char data_in[4096]; - int ret = read(fd, data_in, sizeof(data_in)); - if (ret < 0) - return; - if (ret == 0) { - close_fd(fd); - fd_closed = true; - return; - } - data.append(data_in, ret); - if (ret == sizeof(data_in)) - return; - } catch ( ... ) { - close_fd(fd); - fd_closed = true; - } - } - - if (poll_info.revents & (POLLERR | POLLHUP | POLLNVAL)) { - close_fd(fd); - fd_closed = true; - return; - } + int fd = poll_info.fd; + + if (poll_info.revents & POLLIN) { + try { + char data_in[4096]; + int ret = read(fd, data_in, sizeof(data_in)); + if (ret < 0) + return; + if (ret == 0) { + close_fd(fd); + fd_closed = true; + return; + } + data.append(data_in, ret); + if (ret == sizeof(data_in)) + return; + } catch ( ... ) { + close_fd(fd); + fd_closed = true; + } + } + + if (poll_info.revents & (POLLERR | POLLHUP | POLLNVAL)) { + close_fd(fd); + fd_closed = true; + return; + } } void close_fd(int fd) { - int e; - do { - e = close(fd); - } while (e && (errno == EINTR)); + int e; + do { + e = close(fd); + } while (e && (errno == EINTR)); } - /* #include using namespace std; @@ -260,25 +260,25 @@ int main(int argc, char** argv) { - String out, err; - int status; - vector arguments; - - String path; - if (argc < 2) { - cout << "enter path to execute: "; - cin >> path; - } else - path = argv[1]; - - for (int i=2; i arguments; + + String path; + if (argc < 2) { + cout << "enter path to execute: "; + cin >> path; + } else + path = argv[1]; + + for (int i=2; i