]> git.lyx.org Git - lyx.git/blobdiff - src/support/syscall.C
the freespacing patch from Kayvan, draw the math empty delim with onoffdash, asure...
[lyx.git] / src / support / syscall.C
index 12d6d26f8288e2cceacaaef16003a61d64f3725e..cea3980137568f37effce1f5e9967f7b68072582 100644 (file)
 #pragma implementation
 #endif
 
+#include <cerrno>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <csignal>
 #include <cstdlib>
-#include <cstdio>
 #include <unistd.h>
+#include "debug.h"
 #include "syscall.h"
 #include "syscontr.h"
 #include "support/lstrings.h"
+#include "support/lyxlib.h"
 
-//----------------------------------------------------------------------
-// Class, which controlls a system-call
-//----------------------------------------------------------------------
-
-// constructor
-Systemcalls::Systemcalls()
-{
-       pid = (pid_t) 0; // yet no child
+Systemcalls::Systemcalls() {
+       pid = 0; // No child yet
 }
 
-// constructor
-// 
-// starts child
-Systemcalls::Systemcalls(Starttype how, string what, Callbackfct cback)
+Systemcalls::Systemcalls(Starttype how, string const & what, Callbackfct cback)
 {
        start   = how;
        command = what;
        cbk     = cback;
-       pid     = (pid_t) 0; // no child yet
+       pid     = static_cast<pid_t>(0);
        retval  = 0;
-       Startscript();
+       startscript();
 }
 
-// destructor
-// not yet implemented (?)
-Systemcalls::~Systemcalls()
-{
+Systemcalls::~Systemcalls() {
+#if 0
+       // If the child is alive, we have to brutally kill it
+       if (getpid() != 0) {
+               lyx::kill(getpid(), SIGKILL);
+       }
+#endif
 }
 
 // Start a childprocess
 // 
 // if child runs in background, add information to global controller.
 
-int Systemcalls::Startscript()
-{
+int Systemcalls::startscript() {
        retval = 0;
        switch (start) {
        case System: 
                retval = system(command.c_str());
-               Callback();
+               callback();
                break;
        case Wait:   
-               pid = Fork();
+               pid = fork();
                if (pid>0) { // Fork succesful. Wait for child
                        waitForChild();
-                       Callback();
+                       callback();
                } else
                        retval = 1;
                break;
        case DontWait:
-               pid=Fork();
+               pid = fork();
                if (pid>0) {
                        // Now integrate into Controller
                        SystemcallsSingletoncontroller::Startcontroller starter;
-                       SystemcallsSingletoncontroller *contr=
-                               starter.GetController();
-                       // Add this to contr
-                       contr->AddCall(*this);
+                       SystemcallsSingletoncontroller * contr = starter.getController();
+                       // Add this to controller
+                       contr->addCall(*this);
                } else
                        retval = 1;
                break;
-               //default:  // error();
-               //break;
        }
        return retval;
 }
 
+void Systemcalls::kill(int /*tolerance*/) {
+       if (getpid() == 0) {
+               lyxerr << "LyX: Can't kill non-existing process." << endl;
+               return;
+       }
+       int ret = lyx::kill(getpid(), SIGHUP);
+       bool wait_for_death = true;
+       if (ret != 0) {
+               if (errno == ESRCH) {
+                       // The process is already dead!
+                       wait_for_death = false;
+               } else {
+                       // Something is rotten - maybe we lost permissions?
+               }
+       }
+       if (wait_for_death) {
+               // Here, we should add the PID to a list of
+               // waiting processes to kill if they are not
+               // dead without tolerance seconds
+#ifdef WITH_WARNINGS
+#warning Implement this using the timer of the singleton systemcontroller (Asger)
+#endif
+       }
+}
+
 
 // Wait for child process to finish. Returns returncode from child.
-void Systemcalls::waitForChild()
-{
+void Systemcalls::waitForChild() {
        // We'll pretend that the child returns 1 on all errorconditions.
        retval = 1;
        int status;
@@ -91,23 +108,25 @@ void Systemcalls::waitForChild()
        while (wait) {
                pid_t waitrpid = waitpid(pid, &status, WUNTRACED);
                if (waitrpid == -1) {
-                       perror("LyX: Error waiting for child");
+                       lyxerr << "LyX: Error waiting for child:" << strerror(errno) << endl;
                        wait = false;
                } else if (WIFEXITED(status)) {
                        // Child exited normally. Update return value.
                        retval = WEXITSTATUS(status);
                        wait = false;
                } else if (WIFSIGNALED(status)) {
-                       fprintf(stderr,"LyX: Child didn't catch signal %d "
-                               "and died. Too bad.\n", WTERMSIG(status));
+                       lyxerr << "LyX: Child didn't catch signal "
+                              << WTERMSIG(status) 
+                              << "and died. Too bad." << endl;
                        wait = false;
                } else if (WIFSTOPPED(status)) {
-                       fprintf(stderr,"LyX: Child (pid: %ld) stopped on "
-                               "signal %d. Waiting for child to finish.\n", 
-                               (long) pid, WSTOPSIG(status));
+                       lyxerr << "LyX: Child (pid: " << pid 
+                              << ") stopped on signal "
+                              << WSTOPSIG(status) 
+                              << ". Waiting for child to finish." << endl;
                } else {
-                       fprintf(stderr,"LyX: Something rotten happened while "
-                               "waiting for child %ld\n", (long) pid);
+                       lyxerr << "LyX: Something rotten happened while "
+                               "waiting for child " << pid << endl;
                        wait = false;
                }
        }
@@ -116,9 +135,9 @@ void Systemcalls::waitForChild()
 
 // generate child in background
 
-pid_t Systemcalls::Fork()
+pid_t Systemcalls::fork()
 {
-       pid_t cpid=fork();
+       pid_t cpid= ::fork();
        if (cpid == 0) { // child
                string childcommand(command); // copy
                string rest = split(command, childcommand, ' ');
@@ -126,7 +145,7 @@ pid_t Systemcalls::Fork()
                char *syscmd = 0; 
                char *argv[MAX_ARGV];
                int  index = 0;
-               bool Abbruch;
+               bool more;
                do {
                        if (syscmd == 0) {
                                syscmd = new char[childcommand.length() + 1];
@@ -138,17 +157,17 @@ pid_t Systemcalls::Fork()
                        tmp[childcommand.length()] = '\0';
                        argv[index++] = tmp;
                        // reinit
-                       Abbruch = !rest.empty();
-                       if (Abbruch
+                       more = !rest.empty();
+                       if (more
                                rest = split(rest, childcommand, ' ');
-               } while (Abbruch);
+               } while (more);
                argv[index] = 0;
                // replace by command. Expand using PATH-environment-var.
                execvp(syscmd, argv);
                // If something goes wrong, we end up here:
-               perror("LyX: execvp failed");
+               lyxerr << "LyX: execvp failed: " << strerror(errno) << endl;
        } else if (cpid < 0) { // error
-               perror("LyX: Could not fork");
+               lyxerr << "LyX: Could not fork: " << strerror(errno) << endl;
        } else { // parent
                return cpid;
        }
@@ -158,14 +177,15 @@ pid_t Systemcalls::Fork()
 
 // Reuse of instance
 
-int Systemcalls::Startscript(Starttype how, string what, Callbackfct cback)
+int Systemcalls::startscript(Starttype how, string const & what, 
+                            Callbackfct cback)
 {
        start   = how;
        command = what;
        cbk     = cback;
-       pid     = (pid_t) 0; // yet no child
+       pid     = static_cast<pid_t>(0); // yet no child
        retval  = 0;
-        return Startscript();
+        return startscript();
 }
 
 
@@ -185,11 +205,11 @@ void back(string cmd, int retval)
 }
 
 
-int main(int, char**)
+int main(int, char **)
 {
        
        SystemcallsSingletoncontroller::Startcontroller starter; 
-       SystemcallsSingletoncontroller *contr=starter.GetController();
+       SystemcallsSingletoncontroller *contr= starter.GetController();
        
        Systemcalls one(Systemcalls::System, "ls -ltag", back);
        Systemcalls two(Systemcalls::Wait, "ls -ltag", back);