Changeset 911 for trunk/src


Ignore:
Timestamp:
Jul 25, 2011, 2:36:02 PM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

OS/2: QProcess: Don't close the stdin pipe until the child reads it all.

This fixes the cases when the child process receives truncated data sent to its stdin by the parent process with QProcess::write(). This is due to the fact that writing a chunk of data to a pipe and then closing it will make this data unavailable to the other end if it is not fast enough to read it in between.

Location:
trunk/src/corelib/io
Files:
3 edited

Legend:

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

    r902 r911  
    971971        qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
    972972#endif
     973#if defined Q_OS_OS2
     974        if (stdinChannel.pipe.closePending)
     975            tryCloseStdinPipe();
     976#endif
    973977        return false;
    974978    }
     
    11221126    flushPipeWriter();
    11231127#endif
     1128#ifdef Q_OS_OS2
     1129    // postpone the real close until the other end reads all from the pipe buf
     1130    stdinChannel.pipe.closePending = true;
     1131    tryCloseStdinPipe();
     1132#else
    11241133    destroyPipe(stdinChannel.pipe);
     1134#endif
    11251135}
    11261136
  • trunk/src/corelib/io/qprocess_os2.cpp

    r902 r911  
    553553    pipe.server = HPIPE(~0);
    554554    pipe.client = HFILE(~0);
     555    pipe.closePending = false;
    555556
    556557    // we need the process identifier to guarantee pipe name unicity
     
    612613void QProcessPrivate::destroyPipe(Channel::Pipe &pipe)
    613614{
     615    pipe.closePending = false;
     616
    614617    if (pipe.client != ~HFILE(~0)) {
    615618        DosClose(pipe.client);
     
    634637    channel.pipe.server = HPIPE(~0);
    635638    channel.pipe.client = HFILE(~0);
     639    channel.pipe.closePending = false;
    636640
    637641    if (&channel == &stderrChannel && processChannelMode == QProcess::MergedChannels) {
     
    13421346}
    13431347
     1348void QProcessPrivate::tryCloseStdinPipe()
     1349{
     1350    Q_ASSERT(stdinChannel.pipe.closePending);
     1351
     1352    if (stdinChannel.pipe.closePending) {
     1353        // grab new bytes from QProcessManager (if any)
     1354        int newBytes = pipeData[InPipe].newBytes.fetchAndStoreRelaxed(0);
     1355        if (newBytes)
     1356            pipeData[InPipe].bytesLeft = newBytes;
     1357        if (pipeData[InPipe].bytesLeft == PIPE_SIZE_STDIN) {
     1358            // the other end has read everything from the pipe buf so that it's
     1359            // safe to close it now (satisfy the closeWriteChannel() request)
     1360            destroyPipe(stdinChannel.pipe);
     1361        }
     1362    }
     1363}
     1364
    13441365qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
    13451366{
  • trunk/src/corelib/io/qprocess_p.h

    r846 r911  
    118118            pipe.server = HPIPE(~0);
    119119            pipe.client = HFILE(~0);
     120            pipe.closePending = false;
    120121#else
    121122            pipe[0] = INVALID_Q_PIPE;
     
    155156            HPIPE server;
    156157            HFILE client;
     158            bool closePending;
    157159        };
    158160        Pipe pipe;
     
    243245    void uninit();
    244246    void ensureWaitSem();
     247    void tryCloseStdinPipe();
    245248#endif
    246249
Note: See TracChangeset for help on using the changeset viewer.