Difference between revisions of "147948"

From ThorstensHome
Jump to: navigation, search
(actual result)
(Analysis of kio_fish)
Line 148: Line 148:
 
***** finished
 
***** finished
 
****** writeStdin
 
****** writeStdin
 +
 +
= patch =
 +
The test case almost fails reliably as-is. With the following patch, it works reliably:
 +
<pre>
 +
itchy:~/kdebase/runtime/kioslave/fish # svn diff                               
 +
Index: fish.cpp                                                               
 +
===================================================================           
 +
--- fish.cpp    (revision 904588)                                             
 +
+++ fish.cpp    (working copy)                                                 
 +
@@ -1425,7 +1425,8 @@                                                         
 +
#endif                                                                       
 +
        char buf[32768];                                                     
 +
        int offset = 0;                                                       
 +
-        while (isRunning) {                                                   
 +
+        while (isRunning)                                                     
 +
+        {                                                                     
 +
#ifndef Q_WS_WIN                                                             
 +
            FD_SET(childFd,&rfds);                                           
 +
            FD_ZERO(&wfds);                                                   
 +
@@ -1434,6 +1435,7 @@                                                         
 +
            timeout.tv_sec = 0;                                               
 +
            timeout.tv_usec = 1000;                                           
 +
            rc = select(childFd+1, &rfds, &wfds, NULL, &timeout);             
 +
+            kDebug() << "*******************************************************select returns " << rc;                                                       
 +
            if (rc < 0) {                                                     
 +
                if (errno == EINTR)                                           
 +
                    continue;                                                 
 +
@@ -1444,23 +1446,28 @@                                                       
 +
            }                                                                 
 +
            if (FD_ISSET(childFd,&wfds) && outBufPos >= 0) {                 
 +
#else                                                                         
 +
-            if (outBufPos >= 0) {                                             
 +
+            if (outBufPos >= 0)                                               
 +
+            {                                                                 
 +
#endif                                                                       
 +
#if 0                                                                         
 +
                QString debug;                                               
 +
                debug.setLatin1(outBuf+outBufPos,outBufLen-outBufPos);       
 +
                myDebug( << "now writing " << (outBufLen-outBufPos) << " " << debug.left(40) << "..." << endl);                                               
 +
#endif                                                                       
 +
+                kDebug() << "************************************************************writing to process: " << outBuf;                                     
 +
#ifndef Q_WS_WIN                                                             
 +
                if (outBufLen-outBufPos > 0) rc = ::write(childFd,outBuf+outBufPos,outBufLen-outBufPos);                                                     
 +
#else                                                                         
 +
-                if (outBufLen-outBufPos > 0) {                               
 +
+                if (outBufLen-outBufPos > 0)                                 
 +
+                {
 +
+                    kDebug() << "************************************************************writing to process: " << outBuf;
 +
                    rc = childPid->write(outBuf);
 +
                }
 +
#endif
 +
                else rc = 0;
 +
                if (rc >= 0) outBufPos += rc;
 +
-                else {
 +
+                else
 +
+                {
 +
#ifndef Q_WS_WIN
 +
                    if (errno == EINTR)
 +
                        continue;
 +
@@ -1472,7 +1479,8 @@
 +
                    shutdownConnection();
 +
                    return;
 +
                }
 +
-                if (outBufPos >= outBufLen) {
 +
+                if (outBufPos >= outBufLen)
 +
+                {
 +
                    outBufPos = -1;
 +
                    outBuf = NULL;
 +
                    sent();
 +
@@ -1486,7 +1494,8 @@
 +
                rc = childPid->read(buf+offset,32768-offset);
 +
#endif
 +
                //myDebug( << "read " << rc << " bytes" << endl);
 +
-                if (rc > 0) {
 +
+                if (rc > 0)
 +
+                {
 +
                    int noff = received(buf,rc+offset);
 +
                    if (noff > 0) memmove(buf,buf+offset+rc-noff,noff);
 +
                    //myDebug( << "left " << noff << " bytes: " << QString::fromLatin1(buf,offset) << endl);
 +
</pre>

Revision as of 07:45, 5 January 2009

KDE bug 147948 is about kio_fish stalling. The bug can be reproduced with the following testcase.

Contents

Testcase

files

CMakeLists.txt

PROJECT( browser )
FIND_PACKAGE(KDE4 REQUIRED)
INCLUDE_DIRECTORIES( ${KDE4_INCLUDES} . )


SET(kde4startSources main.cpp browser.cpp )


KDE4_ADD_EXECUTABLE(browser ${kde4startSources} )

TARGET_LINK_LIBRARIES(browser ${KDE4_KDEUI_LIBS} ${KDE4_KPARTS_LIBS} )

install(TARGETS browser  DESTINATION ${BIN_INSTALL_DIR} )

main.cpp

#include <QString>
#include <kapplication.h>
#include <kaboutdata.h>
#include <klocalizedstring.h>
#include <kmessagebox.h>
#include <kcmdlineargs.h>
#include <KMainWindow>
#include <browser.h>

int main (int argc, char *argv[])
{
  const QByteArray& ba=QByteArray("test");
  const KLocalizedString name=ki18n("myName");
  KAboutData aboutData( ba, ba, name, ba, name);
  KCmdLineArgs::init( argc, argv, &aboutData );
  KApplication khello;

  Browser *mw = new Browser();
  mw->show();
  khello.exec();
}

browser.cpp

#include <kio/scheduler.h>       
#include <kurl.h>                
#include <kio/jobclasses.h>      
#include <kdebug.h>              
#include <browser.h>             
#include <kio/copyjob.h>         

class TransferJob;

Browser::Browser() : QWidget(NULL)
{
  slotButtonClicked();
}

void Browser::slotButtonClicked()
{
  kDebug() << "entering function";
  // creating a kioslave
  kDebug() << "getting via fish*************************************************************";
  KUrl::List selectedUrls;

  for (int i=1; i<100; i++)
  {
    QString filename=QString("/tmp/fishtest");
    filename.append(QString::number(i)).append(".txt");
    kDebug() << filename;
    selectedUrls.push_back(KUrl(filename));
  }
  KUrl destUrl("fish://root@localhost/tmp/test");
  KIO::CopyJob* job0 = KIO::copy( selectedUrls, destUrl );
  job0->start();
}

void Browser::dataishere(KIO::Job *,const QByteArray & data )
{
  static int counter=0;
  kDebug() << ++counter << " data is here*************************************************************";
  kDebug() << data;
}

browser.h

#ifndef KDE4START_H__
#define KDE4START_H__

#include <kmainwindow.h>
#include <kio/scheduler.h>
#include <kurl.h>
#include <kio/jobclasses.h>

class Browser : public QWidget
{
  Q_OBJECT
  public:
    Browser();
  public slots:
    void slotButtonClicked();
    void dataishere(KIO::Job *,const QByteArray &);
};
#endif

procedure

for i in $(seq 1 1 100); do touch /tmp/fishtest${i}.txt; done
cmake . && make && ./browser &

expected result

all files are copied

actual result

Only some files are copied. fishProtocol loops endlessly over while (isRunning) in run(). This is because select returns 0.

Analysis of kio_fish

The last words on konsole of kio_fish should be:

fish(2273)/kio_fish fishProtocol::writeStdin: 1231 :  ---------
fish(2273)/kio_fish fishProtocol::handleResponse: 824 :  handling:  "### 200"
fish(2273)/kio_fish fishProtocol::handleResponse: 831 :  result:  200 , errorCount:  0
fish(2273)/kio_fish fishProtocol::finished: 1403 :  _______ emitting finished()

The functions are implemented in /kdebase/runtime/kioslave/fish/fish.cpp

Important commands: fishProtocol::sendCommand; writeStdin

Call graph

  • get
  • put
  • stat
  • mimetype
  • listDir
  • mkdir
  • rename
  • symlink
  • chmod
  • copy
  • del
  • special
    • run
      • received
        • manageConnection
          • handleResponse
          • finished
            • writeStdin

patch

The test case almost fails reliably as-is. With the following patch, it works reliably:

itchy:~/kdebase/runtime/kioslave/fish # svn diff                                
Index: fish.cpp                                                                 
===================================================================             
--- fish.cpp    (revision 904588)                                               
+++ fish.cpp    (working copy)                                                  
@@ -1425,7 +1425,8 @@                                                           
 #endif                                                                         
         char buf[32768];                                                       
         int offset = 0;                                                        
-        while (isRunning) {                                                    
+        while (isRunning)                                                      
+        {                                                                      
 #ifndef Q_WS_WIN                                                               
             FD_SET(childFd,&rfds);                                             
             FD_ZERO(&wfds);                                                    
@@ -1434,6 +1435,7 @@                                                           
             timeout.tv_sec = 0;                                                
             timeout.tv_usec = 1000;                                            
             rc = select(childFd+1, &rfds, &wfds, NULL, &timeout);              
+            kDebug() << "*******************************************************select returns " << rc;                                                        
             if (rc < 0) {                                                      
                 if (errno == EINTR)                                            
                     continue;                                                  
@@ -1444,23 +1446,28 @@                                                         
             }                                                                  
             if (FD_ISSET(childFd,&wfds) && outBufPos >= 0) {                   
 #else                                                                          
-            if (outBufPos >= 0) {                                              
+            if (outBufPos >= 0)                                                
+            {                                                                  
 #endif                                                                         
 #if 0                                                                          
                 QString debug;                                                 
                 debug.setLatin1(outBuf+outBufPos,outBufLen-outBufPos);         
                 myDebug( << "now writing " << (outBufLen-outBufPos) << " " << debug.left(40) << "..." << endl);                                                
 #endif                                                                         
+                kDebug() << "************************************************************writing to process: " << outBuf;                                      
 #ifndef Q_WS_WIN                                                               
                 if (outBufLen-outBufPos > 0) rc = ::write(childFd,outBuf+outBufPos,outBufLen-outBufPos);                                                       
 #else                                                                          
-                if (outBufLen-outBufPos > 0) {                                 
+                if (outBufLen-outBufPos > 0)                                   
+                {
+                    kDebug() << "************************************************************writing to process: " << outBuf;
                     rc = childPid->write(outBuf);
                 }
 #endif
                 else rc = 0;
                 if (rc >= 0) outBufPos += rc;
-                else {
+                else
+                {
 #ifndef Q_WS_WIN
                     if (errno == EINTR)
                         continue;
@@ -1472,7 +1479,8 @@
                     shutdownConnection();
                     return;
                 }
-                if (outBufPos >= outBufLen) {
+                if (outBufPos >= outBufLen)
+                {
                     outBufPos = -1;
                     outBuf = NULL;
                     sent();
@@ -1486,7 +1494,8 @@
                 rc = childPid->read(buf+offset,32768-offset);
 #endif
                 //myDebug( << "read " << rc << " bytes" << endl);
-                if (rc > 0) {
+                if (rc > 0)
+                {
                     int noff = received(buf,rc+offset);
                     if (noff > 0) memmove(buf,buf+offset+rc-noff,noff);
                     //myDebug( << "left " << noff << " bytes: " << QString::fromLatin1(buf,offset) << endl);