modules/fxpackager/src/main/native/library/common/PosixPlatform.cpp

Print this page

        

*** 34,59 **** #include "PosixPlatform.h" #ifdef POSIX #include "PlatformString.h" #include <assert.h> #include <stdbool.h> #include <sys/types.h> #include <unistd.h> #include <sys/sysctl.h> ! #include <dlfcn.h> PosixPlatform::PosixPlatform(void) { } PosixPlatform::~PosixPlatform(void) { } void PosixPlatform::SetCurrentDirectory(TString Value) { chdir(StringToFileSystemString(Value)); } Module PosixPlatform::LoadLibrary(TString FileName) { --- 34,83 ---- #include "PosixPlatform.h" #ifdef POSIX #include "PlatformString.h" + #include "FilePath.h" #include <assert.h> #include <stdbool.h> #include <sys/types.h> #include <unistd.h> #include <sys/sysctl.h> ! #include <iostream> #include <dlfcn.h> + #include <signal.h> PosixPlatform::PosixPlatform(void) { } PosixPlatform::~PosixPlatform(void) { } + MessageResponse PosixPlatform::ShowResponseMessage(TString title, TString description) { + MessageResponse result = mrCancel; + + printf("%s %s (Y/N)\n", PlatformString(title).toPlatformString(), PlatformString(description).toPlatformString()); + fflush(stdout); + + std::string input; + std::cin >> input; + + if (input == "Y") { + result = mrOK; + } + + return result; + } + + //MessageResponse PosixPlatform::ShowResponseMessageB(TString description) { + // TString appname = GetModuleFileName(); + // appname = FilePath::ExtractFileName(appname); + // return ShowResponseMessage(appname, description); + //} + void PosixPlatform::SetCurrentDirectory(TString Value) { chdir(StringToFileSystemString(Value)); } Module PosixPlatform::LoadLibrary(TString FileName) {
*** 76,81 **** --- 100,274 ---- std::vector<TString> PosixPlatform::FilterOutRuntimeDependenciesForPlatform(std::vector<TString> Imports) { std::vector<TString> result; return result; } + Process* PosixPlatform::CreateProcess() { + return new PosixProcess(); + } + + //-------------------------------------------------------------------------------------------------- + + + PosixProcess::PosixProcess() : Process() { + FChildPID = 0; + FRunning = false; + } + + PosixProcess::~PosixProcess() { + Terminate(); + } + + void PosixProcess::Cleanup() { + #ifdef MAC + sigaction(SIGINT, &savintr, (struct sigaction *)0); + sigaction(SIGQUIT, &savequit, (struct sigaction *)0); + sigprocmask(SIG_SETMASK, &saveblock, (sigset_t *)0); + #endif //MAC + } + + bool PosixProcess::IsRunning() { + bool result = false; + + if (kill(FChildPID, 0) == 0) { + result = true; + } + + return result; + } + + bool PosixProcess::Terminate() { + bool result = false; + + if (IsRunning() == true && FRunning == true) { + FRunning = false; + Cleanup(); + int status = kill(FChildPID, SIGTERM); + + if (status == 0) { + result = true; + } + else { + #ifdef DEBUG + if (errno == EINVAL) + printf("Kill error: The value of the sig argument is an invalid or unsupported signal number."); + else if (errno == EPERM) + printf("Kill error: The process does not have permission to send the signal to any receiving process."); + else if (errno == ESRCH) + printf("Kill error: No process or process group can be found corresponding to that specified by pid."); + #endif //DEBUG + if (IsRunning() == true) { + status = kill(FChildPID, SIGKILL); + + if (status == 0) { + result = true; + } + } + } + } + + return result; + } + + bool PosixProcess::Execute(const TString Application, const std::vector<TString> Arguments, bool AWait) { + bool result = false; + + if (FRunning == false) { + FRunning = true; + + struct sigaction sa; + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + #ifdef MAC + sigemptyset(&savintr.sa_mask); + sigemptyset(&savequit.sa_mask); + sigaction(SIGINT, &sa, &savintr); + sigaction(SIGQUIT, &sa, &savequit); + sigaddset(&sa.sa_mask, SIGCHLD); + sigprocmask(SIG_BLOCK, &sa.sa_mask, &saveblock); + #endif //MAC + FChildPID = fork(); + + // PID returned by vfork is 0 for the child process and the PID of the child + // process for the parent. + if (FChildPID == -1) { + // Error + TString message = PlatformString::Format(_T("Error: Unable to create process %s"), Application.data()); + throw Exception(message); + } + else if (FChildPID == 0) { + Cleanup(); + TString command = Application; + + for (std::vector<TString>::const_iterator iterator = Arguments.begin(); iterator != Arguments.end(); iterator++) { + command += TString(_T(" ")) + *iterator; + } + #ifdef DEBUG + printf("%s\n", command.data()); + #endif //DEBUG + execl("/bin/sh", "sh", "-c", command.data(), (char *)0); + _exit(127); + } else { + if (AWait == true) { + Wait(); + Cleanup(); + FRunning = false; + result = true; + } + else { + result = true; + } + } + } + + return result; + } + + bool PosixProcess::Wait() { + bool result = false; + + int status; + pid_t wpid; + + //TODO Use waitpid instead of wait + #ifdef LINUX + wait(); + #endif + #ifdef MAC + wpid = wait(&status); + #endif + + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + if (errno != EINTR){ + status = -1; + } + } + + #ifdef DEBUG + if (WIFEXITED(status)) { + printf("child exited, status=%d\n", WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + printf("child killed (signal %d)\n", WTERMSIG(status)); + } else if (WIFSTOPPED(status)) { + printf("child stopped (signal %d)\n", WSTOPSIG(status)); + #ifdef WIFCONTINUED // Not all implementations support this + } else if (WIFCONTINUED(status)) { + printf("child continued\n"); + #endif //WIFCONTINUED + } else { // Non-standard case -- may never happen + printf("Unexpected status (0x%x)\n", status); + } + #endif //DEBUG + + if (wpid != -1) { + result = true; + } + + return result; + } + + TProcessID PosixProcess::GetProcessID() { + return FChildPID; + } + #endif //POSIX