Browse Source

Some changes to terminal.*. Execution should now be stable on all unix-like systems independent of pclose-implementations.

merge-requests/365/head
eidheim 10 years ago
parent
commit
8098f90b77
  1. 44
      src/terminal.cc
  2. 4
      src/terminal.h
  3. 2
      src/window.cc

44
src/terminal.cc

@ -4,6 +4,7 @@
#include "singletons.h" #include "singletons.h"
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unordered_map>
#include <iostream> //TODO: remove #include <iostream> //TODO: remove
using namespace std; //TODO: remove using namespace std; //TODO: remove
@ -12,6 +13,9 @@ using namespace std; //TODO: remove
#define WRITE 1 #define WRITE 1
int execute_status=-1; int execute_status=-1;
std::mutex execute_status_mutex;
std::unordered_map<pid_t, std::pair<int, int> > async_execute_pid_descriptors;
std::unordered_map<pid_t, int> async_execute_pid_status;
//TODO: Windows... //TODO: Windows...
//Coppied partially from http://www.linuxprogrammingblog.com/code-examples/sigaction //Coppied partially from http://www.linuxprogrammingblog.com/code-examples/sigaction
@ -19,16 +23,16 @@ void signal_execl_exit(int sig, siginfo_t *siginfo, void *context) {
int status; int status;
while (waitpid(siginfo->si_pid, &status, WNOHANG) > 0) {} while (waitpid(siginfo->si_pid, &status, WNOHANG) > 0) {}
Singleton::terminal()->async_pid_mutex.lock(); execute_status_mutex.lock();
if(Singleton::terminal()->async_pid_descriptors.find(siginfo->si_pid)!=Singleton::terminal()->async_pid_descriptors.end()) { if(async_execute_pid_descriptors.find(siginfo->si_pid)!=async_execute_pid_descriptors.end()) {
Singleton::terminal()->async_pid_status[siginfo->si_pid]=status; async_execute_pid_status[siginfo->si_pid]=status;
close(Singleton::terminal()->async_pid_descriptors.at(siginfo->si_pid).first); close(async_execute_pid_descriptors.at(siginfo->si_pid).first);
close(Singleton::terminal()->async_pid_descriptors.at(siginfo->si_pid).second); close(async_execute_pid_descriptors.at(siginfo->si_pid).second);
Singleton::terminal()->async_pid_descriptors.erase(siginfo->si_pid); async_execute_pid_descriptors.erase(siginfo->si_pid);
} }
else else
execute_status=status; execute_status=status;
Singleton::terminal()->async_pid_mutex.unlock(); execute_status_mutex.unlock();
} }
//TODO: Windows... //TODO: Windows...
@ -161,9 +165,11 @@ int Terminal::execute(const std::string &command, const std::string &path) {
while(gtk_events_pending()) while(gtk_events_pending())
gtk_main_iteration(); gtk_main_iteration();
} }
execute_status_mutex.lock();
int exit_code=pclose(p); int exit_code=pclose(p);
if(exit_code!=-1) if(exit_code==-1)
return exit_code; exit_code=execute_status;
execute_status_mutex.unlock();
return execute_status; return execute_status;
} }
} }
@ -182,10 +188,10 @@ void Terminal::async_execute(const std::string &command, const std::string &path
cd_path_and_command=command; cd_path_and_command=command;
int input_descriptor, output_descriptor; int input_descriptor, output_descriptor;
async_pid_mutex.lock(); execute_status_mutex.lock();
auto pid=popen2(cd_path_and_command.c_str(), &input_descriptor, &output_descriptor); auto pid=popen2(cd_path_and_command.c_str(), &input_descriptor, &output_descriptor);
async_pid_descriptors[pid]={input_descriptor, output_descriptor}; async_execute_pid_descriptors[pid]={input_descriptor, output_descriptor};
async_pid_mutex.unlock(); execute_status_mutex.unlock();
if (pid<=0) if (pid<=0)
async_print("Error: Failed to run command" + command + "\n"); async_print("Error: Failed to run command" + command + "\n");
else { else {
@ -197,10 +203,10 @@ void Terminal::async_execute(const std::string &command, const std::string &path
message+=buffer[c]; message+=buffer[c];
async_print(message); async_print(message);
} }
async_pid_mutex.lock(); execute_status_mutex.lock();
int exit_code=async_pid_status.at(pid); int exit_code=async_execute_pid_status.at(pid);
async_pid_status.erase(pid); async_execute_pid_status.erase(pid);
async_pid_mutex.unlock(); execute_status_mutex.unlock();
if(callback) if(callback)
callback(exit_code); callback(exit_code);
} }
@ -209,10 +215,10 @@ void Terminal::async_execute(const std::string &command, const std::string &path
} }
void Terminal::kill_executing() { void Terminal::kill_executing() {
async_pid_mutex.lock(); execute_status_mutex.lock();
for(auto &pid: async_pid_descriptors) for(auto &pid: async_execute_pid_descriptors)
kill(pid.first, SIGTERM); kill(pid.first, SIGTERM);
async_pid_mutex.unlock(); execute_status_mutex.unlock();
} }
int Terminal::print(const std::string &message){ int Terminal::print(const std::string &message){

4
src/terminal.h

@ -7,7 +7,6 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <thread> #include <thread>
#include <atomic> #include <atomic>
#include <unordered_map>
class Terminal : public Gtk::HBox { class Terminal : public Gtk::HBox {
public: public:
@ -28,9 +27,6 @@ public:
Terminal(); Terminal();
int execute(const std::string &command, const std::string &path=""); int execute(const std::string &command, const std::string &path="");
void async_execute(const std::string &command, const std::string &path="", std::function<void(int exit_code)> callback=nullptr); void async_execute(const std::string &command, const std::string &path="", std::function<void(int exit_code)> callback=nullptr);
std::unordered_map<pid_t, std::pair<int, int> > async_pid_descriptors;
std::unordered_map<pid_t, int> async_pid_status;
std::mutex async_pid_mutex;
void kill_executing(); void kill_executing();
int print(const std::string &message); int print(const std::string &message);

2
src/window.cc

@ -212,8 +212,8 @@ void Window::create_menu() {
path+="/"+executables[0].second[0]; path+="/"+executables[0].second[0];
} }
if(cmake.project_path!="") { if(cmake.project_path!="") {
compiling=true;
if(path!="") { if(path!="") {
compiling=true;
Singleton::terminal()->print("Compiling and executing "+path.string()+"\n"); Singleton::terminal()->print("Compiling and executing "+path.string()+"\n");
//TODO: Windows... //TODO: Windows...
Singleton::terminal()->async_execute("make 2>&1", cmake.project_path.string(), [this, path](int exit_code){ Singleton::terminal()->async_execute("make 2>&1", cmake.project_path.string(), [this, path](int exit_code){

Loading…
Cancel
Save