Ignore:
Timestamp:
Aug 11, 2011, 10:57:43 PM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

OS/2: QProcess: Fix hangs when using sync funcs in a GUI program.

An extra asynchronous notification could lead to the same payload being
read from the pipe twice leading to a blocking DosRead call.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/corelib/io/qprocess_os2.cpp

    r964 r969  
    12591259}
    12601260
    1261 qint64 QProcessPrivate::bytesAvailableFromStdout() const
    1262 {
    1263     if (!dying && pipeData[OutPipe].signaled) {
    1264         // reuse the number we stored in _q_notified()
    1265         DEBUG(("QProcessPrivate::bytesAvailableFromStdout() == %lld (reused)",
    1266                pipeData[OutPipe].bytes));
    1267         return pipeData[OutPipe].bytes;
    1268     }
    1269 
     1261// static
     1262qint64 QProcessPrivate::bytesAvailableFromPipe(HPIPE hpipe, bool *closed)
     1263{
    12701264    qint64 bytes = 0;
    1271     if (stdoutChannel.pipe.server != HPIPE(~0) &&
    1272         (!dying || stdoutChannel.type == QProcessPrivate::Channel::Normal)) {
     1265    if (hpipe != HPIPE(~0)) {
    12731266        ULONG state, dummy;
    12741267        AVAILDATA avail;
    1275         APIRET arc = DosPeekNPipe(stdoutChannel.pipe.server, 0, 0, &dummy,
    1276                                   &avail, &state);
     1268        APIRET arc = DosPeekNPipe(hpipe, 0, 0, &dummy, &avail, &state);
    12771269        Q_ASSERT(arc == NO_ERROR);
    12781270        Q_UNUSED(arc);
    12791271        bytes = (qint64)avail.cbpipe;
    1280         if (!dying && state != NP_STATE_CONNECTED) {
    1281             // if the pipe is closed, we negate the result (to preserve the
    1282             // number of bytes remaining) and add -1 to it (to distinguish from
    1283             // the case when there's no data byt the pipe is not closed)
    1284             bytes = -1 - bytes;
    1285         }
     1272        if (closed) {
     1273            *closed = state != NP_STATE_CONNECTED;
     1274        }
     1275    }
     1276    return bytes;
     1277}
     1278
     1279qint64 QProcessPrivate::bytesAvailableFromStdout() const
     1280{
     1281    qint64 bytes = 0;
     1282    if (!dying) {
     1283        Q_ASSERT(pipeData[OutPipe].signaled);
     1284        // reuse the number we got in _q_notified()
     1285        bytes = pipeData[OutPipe].bytes;
     1286    } else {
     1287        if (stdoutChannel.type == QProcessPrivate::Channel::Normal)
     1288            bytes = bytesAvailableFromPipe(stdoutChannel.pipe.server);
    12861289    }
    12871290
     
    12921295qint64 QProcessPrivate::bytesAvailableFromStderr() const
    12931296{
    1294     if (!dying && pipeData[ErrPipe].signaled) {
    1295         // reuse the number we stored in _q_notified()
    1296         DEBUG(("QProcessPrivate::bytesAvailableFromStderr() == %lld (reused)",
    1297                pipeData[ErrPipe].bytes));
    1298         return pipeData[ErrPipe].bytes;
    1299     }
    1300 
    13011297    qint64 bytes = 0;
    1302     if (stderrChannel.pipe.server != HPIPE(~0) &&
    1303         (!dying || stderrChannel.type == QProcessPrivate::Channel::Normal)) {
    1304         ULONG state, dummy;
    1305         AVAILDATA avail;
    1306         APIRET arc = DosPeekNPipe(stderrChannel.pipe.server, 0, 0, &dummy,
    1307                                   &avail, &state);
    1308         Q_ASSERT(arc == NO_ERROR);
    1309         Q_UNUSED(arc);
    1310         bytes = (qint64)avail.cbpipe;
    1311         if (!dying && state != NP_STATE_CONNECTED) {
    1312             // if the pipe is closed, we negate the result (to preserve the
    1313             // number of bytes remaining) and add -1 to it (to distinguish from
    1314             // the case when there's no data byt the pipe is not closed)
    1315             bytes = -1 - bytes;
    1316         }
     1298    if (!dying) {
     1299        Q_ASSERT(pipeData[ErrPipe].signaled);
     1300        // reuse the number we got in _q_notified()
     1301        bytes = pipeData[ErrPipe].bytes;
     1302    } else {
     1303        if (stderrChannel.type == QProcessPrivate::Channel::Normal)
     1304            bytes = bytesAvailableFromPipe(stderrChannel.pipe.server);
    13171305    }
    13181306
     
    16571645    // the remote end of the pipe indicated by bytes < 0
    16581646
     1647
     1648
     1649
     1650
     1651
    16591652    if (flags & CanReadStdOut) {
    1660         qint64 bytes = bytesAvailableFromStdout();
    1661         if (bytes) {
    1662             bool closed = false;
    1663             if (bytes < 0) {
    1664                 bytes = -1 -bytes;
    1665                 closed = true;
    1666             }
     1653        Q_ASSERT(!pipeData[OutPipe].signaled || waitMode);
     1654        bool closed = false;
     1655        qint64 bytes = bytesAvailableFromPipe(stdoutChannel.pipe.server, &closed);
     1656        if (bytes || closed) {
    16671657            pipeData[OutPipe].bytes = bytes;
    16681658            pipeData[OutPipe].signaled = true;
     
    16861676
    16871677    if (flags & CanReadStdErr) {
    1688         qint64 bytes = bytesAvailableFromStderr();
    1689         if (bytes) {
    1690             bool closed = false;
    1691             if (bytes < 0) {
    1692                 bytes = -1 -bytes;
    1693                 closed = true;
    1694             }
     1678        Q_ASSERT(!pipeData[ErrPipe].signaled || waitMode);
     1679        bool closed = false;
     1680        qint64 bytes = bytesAvailableFromPipe(stderrChannel.pipe.server, &closed);
     1681        if (bytes || closed) {
    16951682            pipeData[ErrPipe].bytes = bytes;
    16961683            pipeData[ErrPipe].signaled = true;
Note: See TracChangeset for help on using the changeset viewer.