|
|
@@ -7,112 +7,135 @@ namespace Atomic
|
|
|
{
|
|
|
|
|
|
#include <unistd.h>
|
|
|
+#include <signal.h>
|
|
|
#include <sys/socket.h>
|
|
|
+#include <libproc.h>
|
|
|
#include <errno.h>
|
|
|
|
|
|
#define HANDLE_EINTR(x) ({ \
|
|
|
-typeof(x) __eintr_result__; \
|
|
|
-do { \
|
|
|
-__eintr_result__ = x; \
|
|
|
+ typeof(x) __eintr_result__; \
|
|
|
+ do { \
|
|
|
+ __eintr_result__ = x; \
|
|
|
} while (__eintr_result__ == -1 && errno == EINTR); \
|
|
|
-__eintr_result__;\
|
|
|
+ __eintr_result__;\
|
|
|
})
|
|
|
|
|
|
bool SilenceSocket(int fd) {
|
|
|
- int nosigpipe = 1;
|
|
|
- // On OSX an attempt to read or write to a closed socket may generate a
|
|
|
- // SIGPIPE rather than returning -1. setsockopt will shut this off.
|
|
|
- if (0 != setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE,
|
|
|
- &nosigpipe, sizeof nosigpipe)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
+ int nosigpipe = 1;
|
|
|
+ // On OSX an attempt to read or write to a closed socket may generate a
|
|
|
+ // SIGPIPE rather than returning -1. setsockopt will shut this off.
|
|
|
+ if (0 != setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE,
|
|
|
+ &nosigpipe, sizeof nosigpipe)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
size_t ReadFromFD(int fd, char* buffer, size_t bytes) {
|
|
|
- ssize_t bytes_read =
|
|
|
- HANDLE_EINTR(read(fd, buffer, bytes));
|
|
|
- if (bytes_read < 0) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- return bytes_read;
|
|
|
+
|
|
|
+ fd_set set;
|
|
|
+ struct timeval timeout;
|
|
|
+ FD_ZERO(&set);
|
|
|
+ FD_SET(fd, &set);
|
|
|
+
|
|
|
+ timeout.tv_sec = 0;
|
|
|
+ // 100ms
|
|
|
+ timeout.tv_usec = 100000;
|
|
|
+
|
|
|
+ // check if there is anything to read
|
|
|
+ int rv = select(fd + 1, &set, NULL, NULL, &timeout);
|
|
|
+
|
|
|
+ if (rv < 0)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ if (!rv)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ ssize_t bytes_read =
|
|
|
+ HANDLE_EINTR(read(fd, buffer, bytes));
|
|
|
+ if (bytes_read < 0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return bytes_read;
|
|
|
}
|
|
|
|
|
|
size_t WriteToFD(int fd, const char* data, size_t size) {
|
|
|
- // Allow for partial writes.
|
|
|
- ssize_t written_total = 0;
|
|
|
- for (ssize_t written_partial = 0; written_total < size; written_total += written_partial) {
|
|
|
- written_partial =
|
|
|
- HANDLE_EINTR(write(fd, data + written_total, size - written_total));
|
|
|
- if (written_partial < 0) {
|
|
|
- return -1;
|
|
|
+ // Allow for partial writes.
|
|
|
+ ssize_t written_total = 0;
|
|
|
+ for (ssize_t written_partial = 0; written_total < size; written_total += written_partial) {
|
|
|
+ written_partial =
|
|
|
+ HANDLE_EINTR(write(fd, data + written_total, size - written_total));
|
|
|
+ if (written_partial < 0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- return written_total;
|
|
|
+ return written_total;
|
|
|
}
|
|
|
|
|
|
PipePair::PipePair() {
|
|
|
- fd_[0] = -1;
|
|
|
- fd_[1] = -1;
|
|
|
+ fd_[0] = -1;
|
|
|
+ fd_[1] = -1;
|
|
|
|
|
|
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd_) !=0) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd_) !=0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
PipeUnix::PipeUnix() : fd_(-1) {
|
|
|
}
|
|
|
|
|
|
bool PipeUnix::OpenClient(int fd) {
|
|
|
- if (!SilenceSocket(fd)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- fd_ = fd;
|
|
|
- return true;
|
|
|
+ if (!SilenceSocket(fd)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ fd_ = fd;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
bool PipeUnix::OpenServer(int fd) {
|
|
|
- if (!SilenceSocket(fd)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- fd_ = fd;
|
|
|
- return true;
|
|
|
+ if (!SilenceSocket(fd)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ fd_ = fd;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
|
|
|
bool PipeUnix::Write(const void* buf, size_t sz) {
|
|
|
- if (sz == -1) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- size_t written = WriteToFD(fd_, static_cast<const char*> (buf), sz);
|
|
|
- return (sz == written);
|
|
|
+ if (sz == -1) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ size_t written = WriteToFD(fd_, static_cast<const char*> (buf), sz);
|
|
|
+ return (sz == written);
|
|
|
}
|
|
|
|
|
|
bool PipeUnix::Read(void* buf, size_t* sz) {
|
|
|
- size_t read = ReadFromFD(fd_, static_cast<char*> (buf), *sz);
|
|
|
- if (read == -1) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- *sz = read;
|
|
|
- return true;
|
|
|
+ size_t read = ReadFromFD(fd_, static_cast<char*> (buf), *sz);
|
|
|
+ if (read == -1) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ *sz = read;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
|
|
|
char* PipeTransport::Receive(size_t* size) {
|
|
|
- if (buf_.Size() < kBufferSz) {
|
|
|
- buf_.Resize(kBufferSz);
|
|
|
- }
|
|
|
-
|
|
|
- *size = kBufferSz;
|
|
|
- if (!Read(&buf_[0], size)) {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- return &buf_[0];
|
|
|
+ if (buf_.Size() < kBufferSz) {
|
|
|
+ buf_.Resize(kBufferSz);
|
|
|
+ }
|
|
|
+
|
|
|
+ *size = kBufferSz;
|
|
|
+ if (!Read(&buf_[0], size)) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ return &buf_[0];
|
|
|
}
|
|
|
|
|
|
|
|
|
-IPCProcess::IPCProcess(Context* context) : Object(context),
|
|
|
- pid_(-1)
|
|
|
+IPCProcess::IPCProcess(Context* context, int fd1, int fd2, int pid) : Object(context),
|
|
|
+ pid_(pid),
|
|
|
+ fd1_(fd1),
|
|
|
+ fd2_(fd2)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
@@ -121,9 +144,34 @@ IPCProcess::~IPCProcess()
|
|
|
|
|
|
}
|
|
|
|
|
|
+bool IPCProcess::IsRunning()
|
|
|
+{
|
|
|
+ if (pid_ == -1)
|
|
|
+ return false;
|
|
|
+
|
|
|
+#ifdef __APPLE__
|
|
|
+ char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
|
|
|
+ int ret = proc_pidpath (pid_, pathbuf, sizeof(pathbuf));
|
|
|
+ if ( ret > 0 )
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+#else
|
|
|
+
|
|
|
+ // this doesn't seem to work on OSX?
|
|
|
+ if (kill(pid_, 0) == 0)
|
|
|
+ return true;
|
|
|
+#endif
|
|
|
+
|
|
|
+ return false;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
bool IPCProcess::Launch(const String& command, const Vector<String>& args, const String& initialDirectory)
|
|
|
{
|
|
|
|
|
|
+ assert(pid_ == -1);
|
|
|
+
|
|
|
// We must not allocated memory after fork(),
|
|
|
// therefore allocate all required buffers first.
|
|
|
|