Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-64008

QTemporaryFile::rename fails on non-local filesystems

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P1: Critical
    • 5.10.0 Beta 3
    • 5.10.0 Beta 1
    • Core: I/O
    • None
    • ecryptfs, kernel 4.10
    • ea0e868c4881944207e9b3a77011e05a505ff3b7

    Description

      Ever since

          https://codereview.qt-project.org/#/c/199005/

      was merged, QTemporaryFile::rename fails on Linux 4.10+ due to this kernel bug:

          https://bugzilla.kernel.org/show_bug.cgi?id=197045

      For example, a vanilla Ubuntu 16.04.3 LTS has a kernel with this problem.

      I discovered the problem by accident when trying out the latest Qt Creator snapshot, which gave error dialogs about not being able to write its configuration files.

      This minimal example shows the problem:

      #include <QTemporaryFile>
      #include <QtDebug>
      #include <QtGlobal>
      #include <QSysInfo>
      
      int main(int argc, char *argv[]) {
          qDebug() << "compiled against Qt" << QT_VERSION_STR;
          qDebug() << "running with Qt" << qVersion();
          qDebug() << "running on" << QSysInfo::kernelType() << QSysInfo::kernelVersion();
      
          QTemporaryFile file(argv[1]);
          Q_ASSERT(file.open());
          Q_ASSERT(file.write("Important stuff"));
          Q_ASSERT(file.rename(argv[2]));
      
          return 0;
      }

      With Qt 5.10 beta 1 on Linux 4.10.0-37-generic I get

      [estan@newton renametc]$ ./renametc foo bar
      compiled against Qt 5.10.0
      running with Qt 5.10.0
      running on "linux" "4.10.0-37-generic"
      ASSERT: "file.rename(argv[2])" in file main.cpp, line 14
      Aborted (core dumped)
      [estan@newton renametc]${code}
      and a leftover {{foo.XXXXXX}} in the current directory.
      
      With Qt 5.5.1 I get no error.
      
      The {{strace}} shows the kernel bug:
      {code:java}
      renameat2(AT_FDCWD, "/home/estan/renametc/foo.oFaAKj", AT_FDCWD, "bar", RENAME_NOREPLACE) = -1 EINVAL (Invalid argument)

      This minimal renameat2 program also shows the kernel bug:

      #include <string.h>
      #include <errno.h>
      #include <stdio.h>
      #include <fcntl.h>
      #include <unistd.h>
      #include <sys/syscall.h>
      #include <linux/fs.h>
      
      int main(int argc, char *argv[]) {
          syscall(SYS_renameat2, AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_NOREPLACE);
          printf("%s\n", strerror(errno));
          return 0;
      }

      E.g:

      
      

      [estan@newton renameat2tc]$ touch foo
      [estan@newton renameat2tc]$ ./renameat2 foo bar
      Invalid argument
      [estan@newton renameat2tc]${code}
      On Linux 4.4.0, it works without error.

      Since this is a kernel bug, and recent Qt just happened to be affected by it, I'm not sure what should be done if anything.

      But Ubuntu 16.04 is such a common distro (and has the affected kernel) that I suspect many people will be hit by this, so maybe there's a workaround that could be made in Qt?

      Attachments

        Issue Links

          For Gerrit Dashboard: QTBUG-64008
          # Subject Branch Project Status CR V

          Activity

            People

              thiago Thiago Macieira
              estan Elvis Stansvik
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes