[KIO] silence a QFileInfo warning
Needs ReviewPublic

Authored by rjvbb on Jul 29 2019, 8:32 AM.

Details

Reviewers
None
Group Reviewers
Frameworks
Summary

Prevent qWarning() messages that can arise when browsing samba shares:

QFileInfo::absolutePath: Constructed with empty filename
QFileInfo::absolutePath: Constructed with empty filename
QFileInfo::absolutePath: Constructed with empty filename
# possibly many more

The source of the empty paths isn't clear (see the backtrace in the "Test Plan"); I never noticed the warnings until I upgraded kio-extras to 19.04.3 and Samba to 4.8.9 and my MSWin rig to Win10 1903.
It's probably a good idea to handle this case gracefully.

Test Plan

Backtrace without the patch:

* thread #1, name = 'dolphin', stop reason = breakpoint 1.1
    frame #0: 0x00007ffff10969c7 libQt5Core.so.5`QFileInfo::absolutePath(this=<unavailable>) const at qfileinfo.cpp:586:9
   583      if (d->isDefaultConstructed) {
   584          return QLatin1String("");
   585      } else if (d->fileEntry.isEmpty()) {
-> 586          qWarning("QFileInfo::absolutePath: Constructed with empty filename");
   587          return QLatin1String("");
   588      }
   589      return d->getFileName(QAbstractFileEngine::AbsolutePathName);
(lldb) bt
* thread #1, name = 'dolphin', stop reason = breakpoint 1.1
  * frame #0: 0x00007ffff10969c7 libQt5Core.so.5`QFileInfo::absolutePath(this=<unavailable>) const at qfileinfo.cpp:586:9
    frame #1: 0x00007ffff48442c6 libKF5KIOCore.so.5`KMountPoint::List::findByPath(this=0x00007fffffffd3c0, path=<unavailable>) const at kmountpoint.cpp:422:41
    frame #2: 0x00007ffff6721eaf libKF5KIOWidgets.so.5`KIO::PreviewJobPrivate::startPreview(this=0x0000000000f6bae0) at previewjob.cpp:327:33
    frame #3: 0x00007ffff1180c4e libQt5Core.so.5`QObject::event(this=0x00000000010443e0, e=<unavailable>) at qobject.cpp:1252:18
    frame #4: 0x00007ffff273a84d libQt5Widgets.so.5`QApplicationPrivate::notify_helper(this=<unavailable>, receiver=0x00000000010443e0, e=0x000000000105c690) at qapplication.cpp:3722:31
    frame #5: 0x00007ffff273bba9 libQt5Widgets.so.5`QApplication::notify(this=<unavailable>, receiver=<unavailable>, e=<unavailable>) at qapplication.cpp:0:9
    frame #6: 0x00007ffff1157f53 libQt5Core.so.5`QCoreApplication::notifyInternal2(receiver=0x00000000010443e0, event=0x000000000105c690) at qcoreapplication.cpp:1031:18
    frame #7: 0x00007ffff1158d9f libQt5Core.so.5`QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) [inlined] QCoreApplication::sendEvent(receiver=<unavailable>, event=<unavailable>) at qcoreapplication.h:233:44
    frame #8: 0x00007ffff1158d8b libQt5Core.so.5`QCoreApplicationPrivate::sendPostedEvents(receiver=0x0000000000000000, event_type=0, data=0x000000000061ba50) at qcoreapplication.cpp:1706
    frame #9: 0x00007ffff11a9623 libQt5Core.so.5`postEventSourceDispatch(s=0x000000000078e860, (null)=<unavailable>, (null)=<unavailable>)(void*), void*) at qeventdispatcher_glib.cpp:276:5
    frame #10: 0x00007fffe96bf0e5 libglib-2.0.so.0`g_main_context_dispatch at gmain.c:3170:27
    frame #11: 0x00007fffe96bef57 libglib-2.0.so.0`g_main_context_dispatch(context=<unavailable>) at gmain.c:3835
    frame #12: 0x00007fffe96bf7b5 libglib-2.0.so.0`g_main_context_iterate(context=<unavailable>, block=<unavailable>, dispatch=<unavailable>, self=<unavailable>) at gmain.c:3908:5
    frame #13: 0x00007fffe96bfa21 libglib-2.0.so.0`g_main_context_iteration(context=0x00007fffd8003030, may_block=1) at gmain.c:3969:12
    frame #14: 0x00007ffff11a90db libQt5Core.so.5`QEventDispatcherGlib::processEvents(this=0x0000000000790120, flags=<unavailable>) at qeventdispatcher_glib.cpp:425:18
    frame #15: 0x00007ffff1153baf libQt5Core.so.5`QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) [inlined] QEventLoop::processEvents(this=<unavailable>, flags=<unavailable>) at qeventloop.cpp:134:51
    frame #16: 0x00007ffff1153b95 libQt5Core.so.5`QEventLoop::exec(this=0x00007fffffffda70, flags=<unavailable>) at qeventloop.cpp:212
    frame #17: 0x00007ffff11585fa libQt5Core.so.5`QCoreApplication::exec() at qcoreapplication.cpp:1304:32
    frame #18: 0x00007ffff7b4d753 libkdeinit5_dolphin.so`::kdemain(argc=<unavailable>, argv=<unavailable>) at main.cpp:168:12
    frame #19: 0x00007ffff02d3f45 libc.so.6`__libc_start_main(main=(dolphin`main at dolphin_dummy.cpp:3:43), argc=1, argv=0x00007fffffffdc78, init=<unavailable>, fini=<unavailable>, rtld_fini=<unavailable>, stack_end=0x00007fffffffdc68) at libc-start.c:287
    frame #20: 0x0000000000400979 dolphin`_start + 41

With the patch in place I can browse

Diff Detail

Lint
Lint Skipped
Unit
Unit Tests Skipped
Build Status
Buildable 14523
Build 14541: arc lint + arc unit
rjvbb created this revision.Jul 29 2019, 8:32 AM
Restricted Application added a project: Frameworks. · View Herald TranscriptJul 29 2019, 8:32 AM
rjvbb requested review of this revision.Jul 29 2019, 8:32 AM
rjvbb updated this revision to Diff 62715.Jul 29 2019, 8:37 AM
rjvbb edited the summary of this revision. (Show Details)

It's probably not a bad idea too to return early if ever the computed realname is empty, and avoid the iteration which should be pointless in that case. Right?!

rjvbb set the repository for this revision to R241 KIO.Jul 29 2019, 8:37 AM
meven added a subscriber: meven.Wed, Nov 13, 12:35 PM

The issue could be as well located in previewjob.cpp.
Could you debug why KMountPoint::List::findByPath is called with an empty string or non-existing file.
We might want to prevent this to happen instead.

rjvbb added a comment.Wed, Nov 13, 3:21 PM

Are you not seeing these for instance when browsing an MSWin share in Dolphin (with the same or newer versions of kio-extras, Samba and MSWin)?

I tried to figure out where they came from but failed because of the async nature of the chain of events. I presume the empty paths come from the smb KIO plugin and then somehow make it to where the warning is printed.
I also considered that findByPath() already accepts non-existing paths and handles them appropriately, it could (and probably should) do the same with an empty path. Regardless of the fact that the smb plugin probaby shouldn't output empty paths; maybe the maintainer(s) of that software should be CC'ed here?

meven added a subscriber: dfaure.Thu, Nov 14, 9:18 AM

Are you not seeing these for instance when browsing an MSWin share in Dolphin (with the same or newer versions of kio-extras, Samba and MSWin)?ç

I don't have a samba (or MS) share available currently, unfortunately I can't test, but I might later.

I tried to figure out where they came from but failed because of the async nature of the chain of events. I presume the empty paths come from the smb KIO plugin and then somehow make it to where the warning is printed.

I would suggest adding a dumb qDebug() appriopriately or panic whenever findByPath is called with an emtpy path.
In previewjob.cpp What was PreviewJobPrivate KFileItemList initialItems when this happened ?

I also considered that findByPath() already accepts non-existing ppathsaths and handles them appropriately, it could (and probably should) do the same with an empty path.

I disagree since it will change the current precondition of the function for the need of one of its users.
A warning is an explicit indication that assumption made writing the code are broken either because they are overstepped or were too limited when writing the code.

findPath is documented as :

/**
 * Find the mountpoint on which resides @p path
 * For instance if /home is a separate partition, findByPath("/home/user/blah")
 * will return /home
 * @param path the path to check
 * @return the mount point of the given file
 */
Ptr findByPath(const QString &path) const;

It makes no sense to check the mountpoint of an empty path that by essence cannot be a file.
This might hide others bugs elsewhere.

Regardless of the fact that the smb plugin probaby shouldn't output empty paths; maybe the maintainer(s) of that software should be CC'ed here?

KIO is an old code-base and is maintained collectively mostly (with a single main maintainer @dfaure), we need to use our own wits.

Btw do you use a samba mount(/etc/fstab defined or mount -t smb) or the smb:// ioslave ? You must mean the smb:// ioslave with smb plugin.
In which case we might want to check the samba kio-extras code as well, in particular SMBSlave::listDir that returns the files contained in a folder.
Does it returns files with empty urls ?

I disagree since it will change the current precondition of the function for the need of one of its users.

In that case the warning could be made to be a qDebug, and that user can configure his/her logging setting so the category used will always be printed.
That user might also be served much better by an error return that his/her code could work with, rather than with a terminal warning (which will not be seen by anyone NOT using a terminal to launch applications.

findPath is documented as :

IOW, there is no documentation requirement that warnings be printed for empty path arguments.

It makes no sense to check the mountpoint of an empty path that by essence cannot be a file.

It makes no sense to do that check for any string that is not a valid path. Yet (from memory) there is a specific warning for this particular kind of invalid path.

KIO is an old code-base and is maintained collectively mostly (with a single main maintainer @dfaure), we need to use our own wits.

The smb plugin is part of kio-extras.

Does it returns files with empty urls ?

I have no idea how to check that (other than inserting trace output into smb.so), but I reckon the empty paths must indeed come from there.