summaryrefslogtreecommitdiffstats
path: root/source/core/unix/slang-unix-process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/core/unix/slang-unix-process.cpp')
-rw-r--r--source/core/unix/slang-unix-process.cpp152
1 files changed, 80 insertions, 72 deletions
diff --git a/source/core/unix/slang-unix-process.cpp b/source/core/unix/slang-unix-process.cpp
index ee5484fd8..97b59f21c 100644
--- a/source/core/unix/slang-unix-process.cpp
+++ b/source/core/unix/slang-unix-process.cpp
@@ -1,50 +1,49 @@
// slang-unix-process.cpp
-#include "../slang-process.h"
-
#include "../slang-common.h"
-#include "../slang-string-util.h"
-#include "../slang-string-escape-util.h"
#include "../slang-memory-arena.h"
+#include "../slang-process.h"
+#include "../slang-string-escape-util.h"
+#include "../slang-string-util.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-//#include <dirent.h>
+// #include <dirent.h>
#include <errno.h>
-#include <poll.h>
#include <fcntl.h>
-
+#include <poll.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#if SLANG_OSX
-# include <signal.h>
+#include <signal.h>
#endif
#include <time.h>
-namespace Slang {
+namespace Slang
+{
class UnixProcess : public Process
{
public:
- // Process
+ // Process
virtual bool isTerminated() SLANG_OVERRIDE;
virtual bool waitForTermination(Int timeInMs) SLANG_OVERRIDE;
virtual void terminate(int32_t returnValue) SLANG_OVERRIDE;
virtual void kill(int32_t returnValue) SLANG_OVERRIDE;
- UnixProcess(pid_t pid, Stream*const* streams);
+ UnixProcess(pid_t pid, Stream* const* streams);
protected:
- /// Returns true if terminated
+ /// Returns true if terminated
bool _updateTerminationState(int options);
- bool m_isTerminated = false; ///< True if ths process is terminated
- pid_t m_pid; ///< The process id
+ bool m_isTerminated = false; ///< True if ths process is terminated
+ pid_t m_pid; ///< The process id
};
class UnixPipeStream : public Stream
@@ -54,7 +53,12 @@ public:
// Stream
virtual Int64 getPosition() SLANG_OVERRIDE { return 0; }
- virtual SlangResult seek(SeekOrigin origin, Int64 offset) SLANG_OVERRIDE { SLANG_UNUSED(origin); SLANG_UNUSED(offset); return SLANG_E_NOT_AVAILABLE; }
+ virtual SlangResult seek(SeekOrigin origin, Int64 offset) SLANG_OVERRIDE
+ {
+ SLANG_UNUSED(origin);
+ SLANG_UNUSED(offset);
+ return SLANG_E_NOT_AVAILABLE;
+ }
virtual SlangResult read(void* buffer, size_t length, size_t& outReadBytes) SLANG_OVERRIDE;
virtual SlangResult write(const void* buffer, size_t length) SLANG_OVERRIDE;
virtual bool isEnd() SLANG_OVERRIDE { return m_isClosed; }
@@ -63,18 +67,15 @@ public:
virtual void close() SLANG_OVERRIDE;
virtual SlangResult flush() SLANG_OVERRIDE;
- UnixPipeStream(int fd, FileAccess access, bool isOwned) :
- m_fd(fd),
- m_access(access),
- m_isOwned(isOwned),
- m_isClosed(false)
+ UnixPipeStream(int fd, FileAccess access, bool isOwned)
+ : m_fd(fd), m_access(access), m_isOwned(isOwned), m_isClosed(false)
{
}
protected:
- /// This read file descriptor non blocking. Doing so will change the behavior of
- /// read - it can fail and return an error indicating there is no data, instead of blocking.
- /// Currently this mechanism isn't used, as checking via poll seemed to work.
+ /// This read file descriptor non blocking. Doing so will change the behavior of
+ /// read - it can fail and return an error indicating there is no data, instead of blocking.
+ /// Currently this mechanism isn't used, as checking via poll seemed to work.
void _setReadNonBlocking()
{
// Makes non blocking
@@ -86,16 +87,16 @@ protected:
}
bool _has(FileAccess access) const { return (Index(access) & Index(m_access)) != 0; }
- bool m_isClosed; ///< If true this stream has been closed (ie cannot read/write to anymore)
- bool m_isOwned; ///< True if m_fd is owned by this object.
- FileAccess m_access; ///< Access allowed to this stream - either Read or Write
- int m_fd; /// The 'file descriptor' for the pipe
+ bool m_isClosed; ///< If true this stream has been closed (ie cannot read/write to anymore)
+ bool m_isOwned; ///< True if m_fd is owned by this object.
+ FileAccess m_access; ///< Access allowed to this stream - either Read or Write
+ int m_fd; /// The 'file descriptor' for the pipe
};
/* !!!!!!!!!!!!!!!!!!!!!! UnixProcess !!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-UnixProcess::UnixProcess(pid_t pid, Stream* const* streams):
- m_pid(pid)
+UnixProcess::UnixProcess(pid_t pid, Stream* const* streams)
+ : m_pid(pid)
{
// Set to an 'odd value'
m_returnValue = -1;
@@ -145,15 +146,16 @@ bool UnixProcess::waitForTermination(Int timeInMs)
// If < 0 we will wait blocking until terminated
if (timeInMs < 0)
{
- while (!_updateTerminationState(0));
+ while (!_updateTerminationState(0))
+ ;
return true;
}
- // Note that the amount of time waiting is very approximate (we are relying on sleeps time and don't take into
- // account time outside of sleeping)
+ // Note that the amount of time waiting is very approximate (we are relying on sleeps time and
+ // don't take into account time outside of sleeping)
// How often to test
- const Int checkRateMs = 100; /// Check every 0.1 seconds
+ const Int checkRateMs = 100; /// Check every 0.1 seconds
while (timeInMs > 0)
{
@@ -283,7 +285,7 @@ SlangResult UnixPipeStream::read(void* buffer, size_t length, size_t& outReadByt
{
return SLANG_OK;
}
- // Okay - guess we have an error then
+ // Okay - guess we have an error then
return SLANG_FAIL;
}
@@ -291,7 +293,7 @@ SlangResult UnixPipeStream::read(void* buffer, size_t length, size_t& outReadByt
// If no bytes were wanted, then there could still be bytes in the pipe
// before a HUP. So don't fall through to check for HUP.
- //
+ //
// If some bytes *were* wanted and none were read, we can allow fall through to
// handle HUP.
if (length == 0 || count > 0)
@@ -355,7 +357,7 @@ SlangResult UnixPipeStream::write(const void* buffer, size_t length)
/* !!!!!!!!!!!!!!!!!!!!!! Process !!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-/* static */UnownedStringSlice Process::getExecutableSuffix()
+/* static */ UnownedStringSlice Process::getExecutableSuffix()
{
#if __CYGWIN__
return UnownedStringSlice::fromLiteral(".exe");
@@ -364,7 +366,7 @@ SlangResult UnixPipeStream::write(const void* buffer, size_t length)
#endif
}
-/* static */StringEscapeHandler* Process::getEscapeHandler()
+/* static */ StringEscapeHandler* Process::getEscapeHandler()
{
return StringEscapeUtil::getHandler(StringEscapeUtil::Style::Space);
}
@@ -377,9 +379,8 @@ static int pipeCLOEXEC(int pipefd[2])
// without pipe2 on macOS, there's an unavoidable race here where
// another process could fork and execv with execWatchPipe before we
// can set CLOEXEC on it...
- if(pipe(pipefd) == -1 ||
- fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) == -1 ||
- fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) == -1)
+ if (pipe(pipefd) == -1 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) == -1 ||
+ fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) == -1)
{
return -1;
}
@@ -389,7 +390,10 @@ static int pipeCLOEXEC(int pipefd[2])
#endif
}
-/* static */SlangResult Process::create(const CommandLine& commandLine, Process::Flags, RefPtr<Process>& outProcess)
+/* static */ SlangResult Process::create(
+ const CommandLine& commandLine,
+ Process::Flags,
+ RefPtr<Process>& outProcess)
{
const char* whatFailed = nullptr;
pid_t childPid;
@@ -404,7 +408,7 @@ static int pipeCLOEXEC(int pipefd[2])
// Add the command
argPtrs.add(exe.m_pathOrName.getBuffer());
- // Add all the args - they don't need any explicit escaping
+ // Add all the args - they don't need any explicit escaping
for (auto arg : commandLine.m_args)
{
// All args for this target must be unescaped (as they are in CommandLine)
@@ -425,9 +429,7 @@ static int pipeCLOEXEC(int pipefd[2])
// automatically if the child's exec succeeds
int execWatchPipe[2] = {-1, -1};
- if (pipe(stdinPipe) == -1 ||
- pipe(stdoutPipe) == -1 ||
- pipe(stderrPipe) == -1 ||
+ if (pipe(stdinPipe) == -1 || pipe(stdoutPipe) == -1 || pipe(stderrPipe) == -1 ||
pipeCLOEXEC(execWatchPipe) == -1)
{
whatFailed = "pipe";
@@ -438,36 +440,36 @@ static int pipeCLOEXEC(int pipefd[2])
// 0,1,2 in the child.
whatFailed = "fcntl";
int next;
- if(stdinPipe[0] < 3)
+ if (stdinPipe[0] < 3)
{
- if(-1 == (next = fcntl(stdinPipe[0], F_DUPFD, 3)))
+ if (-1 == (next = fcntl(stdinPipe[0], F_DUPFD, 3)))
{
goto reportErr;
}
close(stdinPipe[0]);
stdinPipe[0] = next;
}
- if(stdoutPipe[1] < 3)
+ if (stdoutPipe[1] < 3)
{
- if(-1 == (next = fcntl(stdoutPipe[1], F_DUPFD, 3)))
+ if (-1 == (next = fcntl(stdoutPipe[1], F_DUPFD, 3)))
{
goto reportErr;
}
close(stdoutPipe[1]);
stdoutPipe[1] = next;
}
- if(stderrPipe[1] < 3)
+ if (stderrPipe[1] < 3)
{
- if(-1 == (next = fcntl(stderrPipe[1], F_DUPFD, 3)))
+ if (-1 == (next = fcntl(stderrPipe[1], F_DUPFD, 3)))
{
goto reportErr;
}
close(stderrPipe[1]);
stderrPipe[1] = next;
}
- if(execWatchPipe[1] < 3)
+ if (execWatchPipe[1] < 3)
{
- if(-1 == (next = fcntl(execWatchPipe[1], F_DUPFD_CLOEXEC, 3)))
+ if (-1 == (next = fcntl(execWatchPipe[1], F_DUPFD_CLOEXEC, 3)))
{
goto reportErr;
}
@@ -516,14 +518,14 @@ static int pipeCLOEXEC(int pipefd[2])
// Signal the failure to our parent
int execErr = errno;
- if(::write(execWatchPipe[1], &execErr, sizeof(execErr)))
+ if (::write(execWatchPipe[1], &execErr, sizeof(execErr)))
fprintf(stderr, "error: `exec` watch pipe write failed\n");
// NOTE! Because we have dup2 into STDERR_FILENO, this error will *not* generally appear on
- // the terminal but in the stderrPipe.
+ // the terminal but in the stderrPipe.
fprintf(stderr, "error: `exec` failed\n");
- // Terminate with failure.
+ // Terminate with failure.
// Call _exit() rather than exit() so we don't run anything registered with atexit()
::_exit(kCannotExecute);
}
@@ -538,11 +540,14 @@ static int pipeCLOEXEC(int pipefd[2])
RefPtr<Stream> streams[Index(StdStreamType::CountOf)];
// Previously code didn't need to close, so we'll make stream now own the handles
- streams[Index(StdStreamType::Out)] = new UnixPipeStream(stdoutPipe[0], FileAccess::Read, true);
+ streams[Index(StdStreamType::Out)] =
+ new UnixPipeStream(stdoutPipe[0], FileAccess::Read, true);
stdoutPipe[0] = -1;
- streams[Index(StdStreamType::ErrorOut)] = new UnixPipeStream(stderrPipe[0], FileAccess::Read, true);
+ streams[Index(StdStreamType::ErrorOut)] =
+ new UnixPipeStream(stderrPipe[0], FileAccess::Read, true);
stderrPipe[0] = -1;
- streams[Index(StdStreamType::In)] = new UnixPipeStream(stdinPipe[1], FileAccess::Write, true);
+ streams[Index(StdStreamType::In)] =
+ new UnixPipeStream(stdinPipe[1], FileAccess::Write, true);
stdinPipe[1] = -1;
// Check that the exec actually succeeded
@@ -550,7 +555,7 @@ static int pipeCLOEXEC(int pipefd[2])
// Our success is if we read zero bytes, indicating that the pipe was
// closed by the child's exec and O_CLOEXEC. (and us just above)
const int readRes = ::read(execWatchPipe[0], &execErrCode, sizeof(execErrCode));
- if(readRes < 0)
+ if (readRes < 0)
{
whatFailed = "read from forked process";
goto reportErr;
@@ -563,11 +568,14 @@ static int pipeCLOEXEC(int pipefd[2])
const bool verbose = false;
if (verbose)
{
- fprintf(stderr, "error: exec for \"%s\" failed: %s\n", argPtrs[0],
- ::strerror(execErrCode));
+ fprintf(
+ stderr,
+ "error: exec for \"%s\" failed: %s\n",
+ argPtrs[0],
+ ::strerror(execErrCode));
}
whatFailed = "exec";
- // Don't report the exec as we expect some of them to fail
+ // Don't report the exec as we expect some of them to fail
goto closePipes;
}
@@ -592,19 +600,19 @@ closePipes:
return whatFailed ? SLANG_FAIL : SLANG_OK;
}
-/* static */uint64_t Process::getClockFrequency()
+/* static */ uint64_t Process::getClockFrequency()
{
return 1000000000;
}
-/* static */uint64_t Process::getClockTick()
+/* static */ uint64_t Process::getClockTick()
{
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
return uint64_t(now.tv_sec) * 1000000000 + now.tv_nsec;
}
-/* static */void Process::sleepCurrentThread(Int timeInMs)
+/* static */ void Process::sleepCurrentThread(Int timeInMs)
{
struct timespec timeSpec;
@@ -626,26 +634,26 @@ closePipes:
nanosleep(&timeSpec, nullptr);
}
-/* static */SlangResult Process::getStdStream(StdStreamType type, RefPtr<Stream>& out)
+/* static */ SlangResult Process::getStdStream(StdStreamType type, RefPtr<Stream>& out)
{
switch (type)
{
- case StdStreamType::In:
+ case StdStreamType::In:
{
out = new UnixPipeStream(STDIN_FILENO, FileAccess::Read, false);
break;
}
- case StdStreamType::Out:
+ case StdStreamType::Out:
{
out = new UnixPipeStream(STDOUT_FILENO, FileAccess::Write, false);
- break;
+ break;
}
- case StdStreamType::ErrorOut:
+ case StdStreamType::ErrorOut:
{
out = new UnixPipeStream(STDERR_FILENO, FileAccess::Write, false);
break;
}
- default: return SLANG_FAIL;
+ default: return SLANG_FAIL;
}
return SLANG_OK;
}