[rkward-cvs] SF.net SVN: rkward:[3662] trunk/rkward/rkward/rbackend
tfry at users.sourceforge.net
tfry at users.sourceforge.net
Thu Jun 2 21:36:16 UTC 2011
Revision: 3662
http://rkward.svn.sourceforge.net/rkward/?rev=3662&view=rev
Author: tfry
Date: 2011-06-02 21:36:15 +0000 (Thu, 02 Jun 2011)
Log Message:
-----------
Fix deadlock issues in stdout-handling, and further cleanups
Modified Paths:
--------------
trunk/rkward/rkward/rbackend/rkbackendtransmitter.cpp
trunk/rkward/rkward/rbackend/rkfrontendtransmitter.cpp
trunk/rkward/rkward/rbackend/rkfrontendtransmitter.h
trunk/rkward/rkward/rbackend/rkrbackend.cpp
trunk/rkward/rkward/rbackend/rkrbackend.h
trunk/rkward/rkward/rbackend/rkrbackendprotocol_backend.cpp
Modified: trunk/rkward/rkward/rbackend/rkbackendtransmitter.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkbackendtransmitter.cpp 2011-06-02 18:19:29 UTC (rev 3661)
+++ trunk/rkward/rkward/rbackend/rkbackendtransmitter.cpp 2011-06-02 21:36:15 UTC (rev 3662)
@@ -63,6 +63,7 @@
connection->write ("\n");
connection->write (RKWARD_VERSION);
connection->write ("\n");
+ connection->waitForBytesWritten ();
QTimer* flush_timer = new QTimer (this);
connect (flush_timer, SIGNAL (timeout()), this, SLOT (flushOutput()));
@@ -115,7 +116,7 @@
void RKRBackendTransmitter::flushOutput (bool force) {
if (!current_sync_requests.isEmpty ()) return;
- if (!RKRBackend::this_pointer->fetchStdoutStderr (force, false)) return;
+ RKRBackend::this_pointer->fetchStdoutStderr (force);
ROutputList out = RKRBackend::this_pointer->flushOutput (force);
if (out.isEmpty ()) return;
Modified: trunk/rkward/rkward/rbackend/rkfrontendtransmitter.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkfrontendtransmitter.cpp 2011-06-02 18:19:29 UTC (rev 3661)
+++ trunk/rkward/rkward/rbackend/rkfrontendtransmitter.cpp 2011-06-02 21:36:15 UTC (rev 3662)
@@ -61,7 +61,6 @@
args.append ("--debug-level " + QString::number (RK_Debug_Level));
args.append ("--server-name " + server->fullServerName ());
args.append ("--data-dir " + RKSettingsModuleGeneral::filesPath ());
- backend->setProcessChannelMode (QProcess::MergedChannels); // at least for now. Seems difficult to get interleaving right, without this.
connect (backend, SIGNAL (finished (int, QProcess::ExitStatus)), this, SLOT (backendExit (int)));
QString backend_executable = KStandardDirs::findExe (QDir::toNativeSeparators (QCoreApplication::applicationDirPath () + "/rkward.rbackend"));
if (backend_executable.isEmpty ()) backend_executable = KStandardDirs::findExe (QDir::toNativeSeparators (QCoreApplication::applicationDirPath () + "/rbackend/rkward.rbackend")); // for running directly from the build-dir
@@ -70,15 +69,10 @@
// fetch security token
if (!backend->canReadLine ()) backend->waitForReadyRead ();
- token = QString::fromLocal8Bit (backend->readLine ());
- token.chop (1);
-#ifdef Q_WS_WIN
- token.chop (1); // '\r', I suppose...
-#endif
+ token = QString::fromLocal8Bit (backend->readLine ()).trimmed ();
+ backend->closeReadChannel (QProcess::StandardError);
+ backend->closeReadChannel (QProcess::StandardOutput);
- connect (backend, SIGNAL (readyReadStandardOutput ()), this, SLOT (newProcessOutput ()));
- if (backend->bytesAvailable ()) newProcessOutput ();
-
exec ();
if (!connection) {
@@ -110,13 +104,6 @@
setConnection (con);
}
-void RKFrontendTransmitter::newProcessOutput () {
- RK_TRACE (RBACKEND);
-
- QString output = QString::fromLocal8Bit (backend->readAll ());
- handleOutput (output, output.size (), ROutput::Warning);
-}
-
void RKFrontendTransmitter::requestReceived (RBackendRequest* request) {
RK_TRACE (RBACKEND);
Modified: trunk/rkward/rkward/rbackend/rkfrontendtransmitter.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkfrontendtransmitter.h 2011-06-02 18:19:29 UTC (rev 3661)
+++ trunk/rkward/rkward/rbackend/rkfrontendtransmitter.h 2011-06-02 21:36:15 UTC (rev 3662)
@@ -39,7 +39,6 @@
void requestReceived (RBackendRequest *request);
private slots:
void connectAndEnterLoop ();
- void newProcessOutput ();
void backendExit (int exitcode);
private:
void handleTransmissionError (const QString &message);
Modified: trunk/rkward/rkward/rbackend/rkrbackend.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.cpp 2011-06-02 18:19:29 UTC (rev 3661)
+++ trunk/rkward/rkward/rbackend/rkrbackend.cpp 2011-06-02 21:36:15 UTC (rev 3662)
@@ -383,7 +383,7 @@
}
#endif
-bool RKRBackend::fetchStdoutStderr (bool forcibly, bool allow_blocking) {
+bool RKRBackend::fetchStdoutStderr (bool forcibly) {
#ifndef Q_OS_WIN
if (!forcibly) {
if (!stdout_stderr_mutex.tryLock ()) return false;
@@ -391,14 +391,15 @@
stdout_stderr_mutex.lock ();
}
+ // it seems, setting this only once is not always enough.
+ fcntl (stdout_stderr_fd, F_SETFL, fcntl (stdout_stderr_fd, F_GETFL, 0) | O_NONBLOCK);
char buffer[1024];
while (true) {
int bytes = read (stdout_stderr_fd, buffer, 1023);
- if (bytes < 0) break;
- if (bytes != 0) {
- buffer[bytes] = '\0';
- handleOutput (current_locale_codec->toUnicode (buffer, bytes), bytes, ROutput::Warning, allow_blocking);
- }
+ if (bytes <= 0) break;
+ buffer[bytes] = '\0';
+ // NOTE: we must not risk blocking inside handleOutput, while the stdout_stderr_mutex is locked!
+ handleOutput (current_locale_codec->toUnicode (buffer, bytes), bytes, ROutput::Warning, false);
}
stdout_stderr_mutex.unlock ();
@@ -425,7 +426,7 @@
}
}
- RKRBackend::this_pointer->fetchStdoutStderr (true, true);
+ RKRBackend::this_pointer->fetchStdoutStderr (true);
RKRBackend::this_pointer->handleOutput (RKRBackend::this_pointer->current_locale_codec->toUnicode (buf, buflen), buflen, type == 0 ? ROutput::Output : ROutput::Warning);
}
@@ -960,13 +961,10 @@
#ifndef Q_OS_WIN
// re-direct stdout / stderr to a pipe, so we can read output from system() calls
int pfd[2];
- pipe(pfd);
- for (int n=0; n<2; n++) {
- fcntl (pfd[n], F_SETFL, fcntl (pfd[n], F_GETFL, 0) | O_NONBLOCK);
- }
- dup2(STDOUT_FILENO, STDERR_FILENO); // single channel to avoid interleaving hell, for now.
- dup2(pfd[1], STDOUT_FILENO);
- close(pfd[1]);
+ pipe (pfd);
+ dup2 (STDOUT_FILENO, STDERR_FILENO); // single channel to avoid interleaving hell, for now.
+ dup2 (pfd[1], STDOUT_FILENO);
+ close (pfd[1]);
stdout_stderr_fd = pfd[0];
#endif
Modified: trunk/rkward/rkward/rbackend/rkrbackend.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.h 2011-06-02 18:19:29 UTC (rev 3661)
+++ trunk/rkward/rkward/rbackend/rkrbackend.h 2011-06-02 21:36:15 UTC (rev 3662)
@@ -187,7 +187,7 @@
/** check stdout and stderr for new output (from sub-processes). Since this function is called from both threads, it is protected by a mutex.
* @param forcibly: if false, and the other thread currently has a lock on the mutex, do nothing, and return false.
* @returns: true, if output was actually fetched (or no output was available), false, if the function gave up on a locked mutex. */
- bool fetchStdoutStderr (bool forcibly, bool allow_blocking);
+ bool fetchStdoutStderr (bool forcibly);
private:
void clearPendingInterrupt ();
protected:
Modified: trunk/rkward/rkward/rbackend/rkrbackendprotocol_backend.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackendprotocol_backend.cpp 2011-06-02 18:19:29 UTC (rev 3661)
+++ trunk/rkward/rkward/rbackend/rkrbackendprotocol_backend.cpp 2011-06-02 21:36:15 UTC (rev 3662)
@@ -32,6 +32,7 @@
# include "kcomponentdata.h"
# include "kglobal.h"
# include "rktransmitter.h"
+# include <stdio.h>
#endif
#ifdef RKWARD_THREADED
@@ -104,6 +105,9 @@
KComponentData data ("rkward");
KGlobal::locale (); // to initialize it in the primary thread
+ setvbuf (stdout, NULL, _IONBF, 0);
+ setvbuf (stderr, NULL, _IONBF, 0);
+
RK_Debug_File = new KTemporaryFile ();
RK_Debug_File->setPrefix ("rkward.rbackend");
RK_Debug_File->setAutoRemove (false);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the rkward-tracker
mailing list