Changeset 188
- Timestamp:
- Nov 21, 2008, 4:36:19 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel/qprocess_pm.cpp
r186 r188 143 143 QProcessPrivate( QProcess *proc ) 144 144 { 145 145 stdinBufRead = 0; 146 146 pipeStdin = HP_NULL; 147 147 pid = PID_NULL; 148 149 150 151 148 exitValuesCalculated = FALSE; 149 150 lookup = new QTimer( proc ); 151 qApp->connect( lookup, SIGNAL(timeout()), proc, SLOT(timeout()) ); 152 152 } 153 153 154 154 ~QProcessPrivate() 155 155 { 156 156 reset(); 157 157 } 158 158 159 159 void reset() 160 160 { 161 162 163 164 165 161 while ( !stdinBuf.isEmpty() ) { 162 delete stdinBuf.dequeue(); 163 } 164 stdinBufRead = 0; 165 closeHandles(); 166 166 stdout.buf.clear(); 167 167 stderr.buf.clear(); 168 169 168 pid = PID_NULL; 169 exitValuesCalculated = FALSE; 170 170 } 171 171 … … 237 237 bool addProcess( QProcess *proc ); 238 238 void removeProcess( QProcessPrivate *d, 239 QProcessPrivate::Pipe *pipe = NULL ); 239 QProcessPrivate::Pipe *pipe = NULL, 240 bool inMsgHandler = false); 240 241 241 242 void monitor(); … … 405 406 406 407 void QProcessMonitor::removeProcess( QProcessPrivate *d, 407 QProcessPrivate::Pipe *pipe /* = NULL */) 408 QProcessPrivate::Pipe *pipe /* = NULL */, 409 bool inMsgHandler /* = false */) 408 410 { 409 411 #if defined(QT_QPROCESS_DEBUG) … … 424 426 return; 425 427 } 426 428 429 if ( !inMsgHandler ) { 430 // process all messages in the message queue related to QProcessMonitor. 431 // A failure to do so may lead to a situation when another QProcess 432 // started before these messages are processed but after our ends of 433 // pipes are closed (for example, by QProcessPrivate::reset()) gets the 434 // same pipe handles from the system. Since pipe handles are also used 435 // as keys, the delayed messages will then refer to the new QProcess 436 // object they were not intended for. The fix is to remove "our" 437 // messages from the queue now, before closing pipes (which will usually 438 // be done right after this method). 439 440 QMSG qmsg; 441 while (WinPeekMsg (0, &qmsg, hwnd(), WM_U_PIPE_RDATA, WM_U_PIPE_CLOSE, 442 PM_REMOVE)) { 443 qDebug( "msg=%08x", qmsg.msg ); 444 if ( qmsg.msg == WM_U_PIPE_CLOSE ) { 445 QProcess *proc = (QProcess *) PVOIDFROMMP( qmsg.mp1 ); 446 USHORT key = SHORT1FROMMP( qmsg.mp2 ); 447 if ( proc == pipeKeys.find( key ) && proc->d == d ) { 448 // skip the close message for ourselves as we will do all 449 // the necessary stuff 450 continue; 451 } 452 } 453 WinDispatchMsg( 0, &qmsg ); 454 } 455 } 456 427 457 if ( pipe ) { 428 458 removePipe( pipe ); … … 559 589 if ( proc == pipeKeys.find( key ) ) { 560 590 #if defined(QT_QPROCESS_DEBUG) 561 qDebug( "QProcessMonitor::WM_U_PIPE_RDATA: proc=%p (%s/%s) d=%p "562 "key=%04hX",563 proc, proc->name(), proc->className(), proc->d, key );591 qDebug( "QProcessMonitor::WM_U_PIPE_RDATA: proc=%p (%s/%s) d=%p " 592 "key=%04hX", 593 proc, proc->name(), proc->className(), proc->d, key ); 564 594 #endif 565 595 QProcessPrivate *d = proc->d; … … 596 626 Q_ASSERT( pipe->closed ); 597 627 // remove the single pipe from watching 598 removeProcess( d, pipe );628 removeProcess( d, pipe, TRUE /* inMsgHandler */ ); 599 629 // close the pipe since no more necessary 600 630 // (pipe is not watched anymore, no need to lock access) … … 686 716 // the client's end of pipe has been closed, so close our end as well 687 717 if ( processMonitor && pipe->key != KEY_NULL ) { 688 // WM_U_PIPE_CLOSE has been posted but not yet processed: do 689 // nothing in this case and let it do the close job. This is vital 690 // since if we close the pipe now then it's possible that another 691 // QProcess instance created in the meantime will get a pipe with 692 // the same handle from the system (and therefore with the same key) 693 // so our pending WM_U_PIPE_CLOSE message will attempt to close an 694 // invalid (foreign) pipe 695 } 696 else 718 // WM_U_PIPE_CLOSE has been posted but not yet processed 719 // (the following call make sure it will be processed) 720 processMonitor->removeProcess( this, pipe ); 721 } 722 else 697 723 closePipe( pipe ); 698 724 } … … 770 796 771 797 if ( _arguments.isEmpty() ) 772 798 return FALSE; 773 799 774 800 #if defined(QT_QPROCESS_USE_DOSEXECPGM) … … 1479 1505 QProcess *that = (QProcess *) this; 1480 1506 1507 /// @todo the below comment is not relevant any more since removeProcess() 1508 // will dispatch all related messages including WM_U_PIPE_RDATA. Therefore, 1509 // this code should not be needed anymore. 1510 #if 0 1481 1511 // There might be data to read, but WM_U_PIPE_RDATA messages won't be 1482 1512 // converted to signals after removeProcess() is called below. Therefore, … … 1487 1517 if ( d->readPipe( &d->stderr ) ) 1488 1518 emit that->readyReadStderr(); 1519 #endif 1489 1520 1490 1521 // compute the exit values
Note:
See TracChangeset
for help on using the changeset viewer.