mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-23 05:25:26 +00:00
Allow immediate output of spawned processes for all platforms.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@29668 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
ee39b28f99
commit
8fe984090f
@ -12,7 +12,7 @@ BUILT_SOURCES = $(PCH_FILE)
|
||||
######################### Qt stuff #############################
|
||||
#
|
||||
|
||||
MOCHEADER = SignalSlotPrivate.h
|
||||
MOCHEADER = SignalSlotPrivate.h Systemcall.h
|
||||
|
||||
MOCEDFILES = $(MOCHEADER:%.h=moc_%.cpp)
|
||||
|
||||
|
@ -33,6 +33,7 @@ namespace support {
|
||||
|
||||
static void killProcess(QProcess * p)
|
||||
{
|
||||
p->disconnect();
|
||||
p->closeReadChannel(QProcess::StandardOutput);
|
||||
p->closeReadChannel(QProcess::StandardError);
|
||||
p->close();
|
||||
@ -83,7 +84,6 @@ string const parsecmd(string const & cmd, string & outfile)
|
||||
}
|
||||
outfile.erase();
|
||||
return cmd;
|
||||
|
||||
}
|
||||
|
||||
} // namespace anon
|
||||
@ -94,18 +94,15 @@ int Systemcall::startscript(Starttype how, string const & what)
|
||||
string outfile;
|
||||
QString cmd = toqstr(parsecmd(what, outfile));
|
||||
QProcess * process = new QProcess;
|
||||
|
||||
// Qt won't start the process if we redirect stdout/stderr in
|
||||
// this way and they are not connected to a terminal (maybe
|
||||
// because we were launched from some desktop GUI).
|
||||
ConOut console(process);
|
||||
if (!outfile.empty()) {
|
||||
// Check whether we have to simply throw away the output.
|
||||
if (outfile != os::nulldev())
|
||||
process->setStandardOutputFile(toqstr(outfile));
|
||||
} else if (os::is_terminal(os::STDOUT))
|
||||
process->setStandardOutputFile(toqstr(os::stdoutdev()));
|
||||
console.showout();
|
||||
if (os::is_terminal(os::STDERR))
|
||||
process->setStandardErrorFile(toqstr(os::stderrdev()));
|
||||
console.showerr();
|
||||
|
||||
process->start(cmd);
|
||||
if (!process->waitForStarted(3000)) {
|
||||
@ -115,8 +112,10 @@ int Systemcall::startscript(Starttype how, string const & what)
|
||||
LYXERR0("status " << process->exitStatus());
|
||||
return 10;
|
||||
}
|
||||
if (how == DontWait)
|
||||
if (how == DontWait) {
|
||||
// TODO delete process later
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!process->waitForFinished(180000)) {
|
||||
LYXERR0("Qprocess " << cmd << " did not finished!");
|
||||
@ -147,6 +146,57 @@ int Systemcall::startscript(Starttype how, string const & what)
|
||||
killProcess(process);
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
|
||||
ConOut::ConOut(QProcess * proc) : proc_(proc), outindex_(0), errindex_(0),
|
||||
showout_(false), showerr_(false)
|
||||
{
|
||||
connect(proc, SIGNAL(readyReadStandardOutput()), SLOT(stdOut()));
|
||||
connect(proc, SIGNAL(readyReadStandardError()), SLOT(stdErr()));
|
||||
}
|
||||
|
||||
|
||||
ConOut::~ConOut()
|
||||
{
|
||||
cout.flush();
|
||||
cerr.flush();
|
||||
}
|
||||
|
||||
|
||||
void ConOut::stdOut()
|
||||
{
|
||||
if (showout_) {
|
||||
char c;
|
||||
proc_->setReadChannel(QProcess::StandardOutput);
|
||||
while (proc_->getChar(&c)) {
|
||||
outdata_[outindex_++] = c;
|
||||
if (c == '\n' || outindex_ + 1 == bufsize_) {
|
||||
outdata_[outindex_] = '\0';
|
||||
outindex_ = 0;
|
||||
cout << outdata_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConOut::stdErr()
|
||||
{
|
||||
if (showerr_) {
|
||||
char c;
|
||||
proc_->setReadChannel(QProcess::StandardError);
|
||||
while (proc_->getChar(&c)) {
|
||||
errdata_[errindex_++] = c;
|
||||
if (c == '\n' || errindex_ + 1 == bufsize_) {
|
||||
errdata_[errindex_] = '\0';
|
||||
errindex_ = 0;
|
||||
cerr << errdata_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_Systemcall.cpp"
|
||||
#endif
|
||||
|
||||
} // namespace support
|
||||
|
@ -16,6 +16,9 @@
|
||||
#define SYSTEMCALL_H
|
||||
|
||||
#include <string>
|
||||
#include <QObject>
|
||||
|
||||
class QProcess;
|
||||
|
||||
namespace lyx {
|
||||
namespace support {
|
||||
@ -45,6 +48,48 @@ public:
|
||||
int startscript(Starttype how, std::string const & what);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Outputs to the console terminal the line buffered standard output and
|
||||
* error of a spawned process when there is a controlling terminal and
|
||||
* stdout/stderr have not been redirected.
|
||||
*/
|
||||
class ConOut : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ConOut(QProcess * proc);
|
||||
~ConOut();
|
||||
|
||||
/// Should the standard output be displayed?
|
||||
void showout() { showout_ = true; }
|
||||
|
||||
/// Should the standard error be displayed?
|
||||
void showerr() { showerr_ = true; }
|
||||
|
||||
private:
|
||||
/// Pointer to the process to monitor.
|
||||
QProcess * proc_;
|
||||
/// Index to the standard output buffer.
|
||||
size_t outindex_;
|
||||
/// Index to the standard error buffer.
|
||||
size_t errindex_;
|
||||
/// Size of buffers.
|
||||
static size_t const bufsize_ = 200;
|
||||
/// Standard output buffer.
|
||||
char outdata_[bufsize_];
|
||||
/// Standard error buffer.
|
||||
char errdata_[bufsize_];
|
||||
///
|
||||
bool showout_;
|
||||
///
|
||||
bool showerr_;
|
||||
|
||||
public Q_SLOTS:
|
||||
void stdOut();
|
||||
void stdErr();
|
||||
};
|
||||
|
||||
} // namespace support
|
||||
} // namespace lyx
|
||||
|
||||
|
@ -39,12 +39,6 @@ void init(int argc, char * argv[]);
|
||||
/// Returns the name of the NULL device (/dev/null, null).
|
||||
std::string const & nulldev();
|
||||
|
||||
/// Returns the name of the stdout device (/dev/stdout, /dev/tty, conout$).
|
||||
std::string const & stdoutdev();
|
||||
|
||||
/// Returns the name of the stderr device (/dev/stderr, /dev/tty, conout$).
|
||||
std::string const & stderrdev();
|
||||
|
||||
/// Tells whether \p channel is connected to a terminal or not.
|
||||
bool is_terminal(io_channel channel);
|
||||
|
||||
|
@ -240,20 +240,6 @@ string const & nulldev()
|
||||
}
|
||||
|
||||
|
||||
string const & stdoutdev()
|
||||
{
|
||||
static string const stdoutdev_ = "/dev/stdout";
|
||||
return stdoutdev_;
|
||||
}
|
||||
|
||||
|
||||
string const & stderrdev()
|
||||
{
|
||||
static string const stderrdev_ = "/dev/stderr";
|
||||
return stderrdev_;
|
||||
}
|
||||
|
||||
|
||||
bool is_terminal(io_channel channel)
|
||||
{
|
||||
return isatty(channel);
|
||||
|
@ -30,23 +30,8 @@ namespace lyx {
|
||||
namespace support {
|
||||
namespace os {
|
||||
|
||||
namespace {
|
||||
|
||||
string stdoutdev_ = "/dev/stdout";
|
||||
string stderrdev_ = "/dev/stderr";
|
||||
|
||||
} // namespace anon
|
||||
|
||||
void init(int, char *[])
|
||||
{
|
||||
// Check whether /dev/stdout and /dev/stderr are available,
|
||||
// otherwise default to /dev/tty.
|
||||
if (access(stdoutdev_.c_str(), W_OK) != 0
|
||||
|| access(stderrdev_.c_str(), W_OK) != 0) {
|
||||
stdoutdev_ = "/dev/tty";
|
||||
stderrdev_ = "/dev/tty";
|
||||
}
|
||||
}
|
||||
{}
|
||||
|
||||
|
||||
string current_root()
|
||||
@ -145,18 +130,6 @@ string const & nulldev()
|
||||
}
|
||||
|
||||
|
||||
string const & stdoutdev()
|
||||
{
|
||||
return stdoutdev_;
|
||||
}
|
||||
|
||||
|
||||
string const & stderrdev()
|
||||
{
|
||||
return stderrdev_;
|
||||
}
|
||||
|
||||
|
||||
bool is_terminal(io_channel channel)
|
||||
{
|
||||
return isatty(channel);
|
||||
|
@ -296,28 +296,23 @@ string const & nulldev()
|
||||
}
|
||||
|
||||
|
||||
string const & stdoutdev()
|
||||
{
|
||||
static string const stdoutdev_ = "conout$";
|
||||
return stdoutdev_;
|
||||
}
|
||||
|
||||
|
||||
string const & stderrdev()
|
||||
{
|
||||
static string const stderrdev_ = "conout$";
|
||||
return stderrdev_;
|
||||
}
|
||||
|
||||
|
||||
bool is_terminal(io_channel channel)
|
||||
{
|
||||
// FIXME: Passing conout$ to Qt fails, most probably for the
|
||||
// reason explained here:
|
||||
// http://support.microsoft.com/?scid=kb%3Ben-us%3B90088&x=15&y=15
|
||||
// How to convince Qt to open conout$ in FILE_SHARE_WRITE mode?
|
||||
// For the time being, we assume we are not running in a terminal.
|
||||
return false;
|
||||
switch (channel) {
|
||||
case STDIN:
|
||||
if (GetStdHandle(STD_INPUT_HANDLE) == NULL)
|
||||
return false;
|
||||
break;
|
||||
case STDOUT:
|
||||
if (GetStdHandle(STD_OUTPUT_HANDLE) == NULL)
|
||||
return false;
|
||||
break;
|
||||
case STDERR:
|
||||
if (GetStdHandle(STD_ERROR_HANDLE) == NULL)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user