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

Segfault on app exit with plugin unload

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 5.2.0
    • Core: Plugins
    • None

    Description

      The failure at of patch 22 at https://codereview.qt-project.org/#change,53033 is caused by registering a converter function from a plugin. A container is automatically registered in the networkmanager bearer plugin for example. When that plugin is unloaded, the app segfaults on exit. The plugin is unloaded by QPluginFactory.

      The problem can be reduced to the attached testcase. I added a small bit of duplication of the converter registry to the QSortFilterProxyModel class only because it is a leaf-class, and rebuilds are quicker. I also added similar code to QtConcurrent. When the test application invokes the version in QtCore, there is a segfault, but when invoking the one in QtConcurrent, or the local registry in mylib.cpp, there is no segfault on exit.

      commit e8b311d6715059906ff93943af9b0a8966d35952
      Author: Stephen Kelly <stephen.kelly@kdab.com>
      Date:   Tue May 14 10:20:13 2013 +0200
      
          wip: Add some test code.
          
          Change-Id: I43d96866268ac3e91b4930b30a6aa8e94edf917e
      
      diff --git a/src/concurrent/qtconcurrentrun.cpp b/src/concurrent/qtconcurrentrun.cpp
      index 4ab1399..3d2272e 100644
      --- a/src/concurrent/qtconcurrentrun.cpp
      +++ b/src/concurrent/qtconcurrentrun.cpp
      @@ -39,6 +39,41 @@
       **
       ****************************************************************************/
       
      +#include "qtconcurrentrun.h"
      +
      +#include <iostream>
      +
      +
      +class QtConcurrentQMetaTypeConversionRegistry
      +{
      +public:
      +
      +    ~QtConcurrentQMetaTypeConversionRegistry()
      +    {
      +        Q_FOREACH (QtPrivate::AbstractConverterFunction *f, map)
      +            f->destroy(f);
      +        map.clear();
      +    }
      +
      +    bool insertIfNotContains(QtPrivate::AbstractConverterFunction *f)
      +    {
      +        map.push_back(f);
      +        return true;
      +    }
      +
      +private:
      +    QVector<QtPrivate::AbstractConverterFunction *> map;
      +};
      +
      +Q_GLOBAL_STATIC(QtConcurrentQMetaTypeConversionRegistry, QtConcurrentcustomTypesConversionRegistry)
      +
      +bool QtConcurrentregisterConverterFunction(QtPrivate::AbstractConverterFunction *f)
      +{
      +    std::cout << "QtConcurrent REG " << f << std::endl;
      +    QtConcurrentcustomTypesConversionRegistry()->insertIfNotContains(f);
      +    return true;
      +}
      +
       /*!
           \headerfile <QtConcurrentRun>
           \title Asynchronous Run
      diff --git a/src/concurrent/qtconcurrentrun.h b/src/concurrent/qtconcurrentrun.h
      index 0bfe4bf..782f7cd 100644
      --- a/src/concurrent/qtconcurrentrun.h
      +++ b/src/concurrent/qtconcurrentrun.h
      @@ -52,6 +52,7 @@
       
       QT_BEGIN_NAMESPACE
       
      +Q_CONCURRENT_EXPORT bool QtConcurrentregisterConverterFunction(QtPrivate::AbstractConverterFunction *f);
       
       #ifdef Q_QDOC
       
      diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
      index 67b0d98..2b57f51 100644
      --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
      +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
      @@ -52,6 +52,8 @@
       #include <private/qabstractitemmodel_p.h>
       #include <private/qabstractproxymodel_p.h>
       
      +#include <iostream>
      +
       #include <algorithm>
       
       QT_BEGIN_NAMESPACE
      @@ -466,6 +468,37 @@ bool QSortFilterProxyModelPrivate::update_source_sort_column()
       }
       
       
      +
      +class QSortFilterProxyModelQMetaTypeConversionRegistry
      +{
      +public:
      +
      +    ~QSortFilterProxyModelQMetaTypeConversionRegistry()
      +    {
      +        Q_FOREACH (QtPrivate::AbstractConverterFunction *f, map)
      +            f->destroy(f);
      +        map.clear();
      +    }
      +
      +    bool insertIfNotContains(QtPrivate::AbstractConverterFunction *f)
      +    {
      +        map.push_back(f);
      +        return true;
      +    }
      +
      +private:
      +    QVector<QtPrivate::AbstractConverterFunction *> map;
      +};
      +
      +Q_GLOBAL_STATIC(QSortFilterProxyModelQMetaTypeConversionRegistry, QSortFilterProxyModelcustomTypesConversionRegistry)
      +
      +bool QSortFilterProxyModelregisterConverterFunction(QtPrivate::AbstractConverterFunction *f)
      +{
      +    std::cout << "QSortFilterProxyModel REG " << f << std::endl;
      +    QSortFilterProxyModelcustomTypesConversionRegistry()->insertIfNotContains(f);
      +    return true;
      +}
      +
       /*!
         \internal
       
      diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h
      index a37c892..b3bdc73 100644
      --- a/src/corelib/itemmodels/qsortfilterproxymodel.h
      +++ b/src/corelib/itemmodels/qsortfilterproxymodel.h
      @@ -55,6 +55,9 @@ class QSortFilterProxyModelPrivate;
       class QSortFilterProxyModelLessThan;
       class QSortFilterProxyModelGreaterThan;
       
      +Q_CORE_EXPORT bool QSortFilterProxyModelregisterConverterFunction(QtPrivate::AbstractConverterFunction *f);
      +
      +
       class Q_CORE_EXPORT QSortFilterProxyModel : public QAbstractProxyModel
       {
           friend class QSortFilterProxyModelLessThan;
      
      

      I can't explain why there is a segfault when the code in QtCore is invoked, but not elsewhere.

      stephen@hal:~/dev/src/playground/qtpluginbug{master}$ LD_LIBRARY_PATH=$PWD/mylib:$LD_LIBRARY_PATH gdb ./app/app
      GNU gdb (GDB) 7.5.91.20130417-cvs-ubuntu
      Copyright (C) 2013 Free Software Foundation, Inc.
      License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
      This is free software: you are free to change and redistribute it.
      There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
      and "show warranty" for details.
      This GDB was configured as "x86_64-linux-gnu".
      For bug reporting instructions, please see:
      <http://www.gnu.org/software/gdb/bugs/>...
      Reading symbols from /home/stephen/safe/dev/playground/qtpluginbug/app/app...done.
      (gdb) r
      Starting program: /home/stephen/safe/dev/playground/qtpluginbug/app/app 
      [Thread debugging using libthread_db enabled]
      Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
      PluginType(0x6080f0) 
      CREATE
      QSortFilterProxyModel REG 0x609690
      
      Program received signal SIGSEGV, Segmentation fault.
      0x00007ffff3d3b564 in ?? ()
      (gdb) bt
      #0  0x00007ffff3d3b564 in ?? ()
      #1  0x00007ffff78c1850 in QSortFilterProxyModelQMetaTypeConversionRegistry::~QSortFilterProxyModelQMetaTypeConversionRegistry (
          this=0x7ffff7dd9248 <(anonymous namespace)::Q_QGS_QSortFilterProxyModelcustomTypesConversionRegistry::innerFunction()::holder>, __in_chrg=<optimized out>)
          at /home/stephen/dev/src/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp:480
      #2  0x00007ffff78b7e71 in (anonymous namespace)::Q_QGS_QSortFilterProxyModelcustomTypesConversionRegistry::Holder::~Holder (
          this=0x7ffff7dd9248 <(anonymous namespace)::Q_QGS_QSortFilterProxyModelcustomTypesConversionRegistry::innerFunction()::holder>, __in_chrg=<optimized out>)
          at /home/stephen/dev/src/qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp:494
      #3  0x00007ffff6d64121 in __run_exit_handlers (status=0, listp=0x7ffff70e96a8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true) at exit.c:77
      #4  0x00007ffff6d641a5 in __GI_exit (status=<optimized out>) at exit.c:99
      #5  0x00007ffff6d49eac in __libc_start_main (main=0x4010fc <main(int, char**)>, argc=1, ubp_av=0x7fffffffd658, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffd648)
          at libc-start.c:294
      #6  0x0000000000401039 in _start ()
      
      
      stephen@hal:~/dev/src/playground/qtpluginbug{master}$ LD_LIBRARY_PATH=$PWD/mylib:$LD_LIBRARY_PATH valgrind ./app/app
      ==29499== Memcheck, a memory error detector
      ==29499== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
      ==29499== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
      ==29499== Command: ./app/app
      ==29499== 
      PluginType(0x8a10d70) 
      CREATE
      QSortFilterProxyModel REG 0x8a118e0
      ==29499== Jump to the invalid address stated on the next line
      ==29499==    at 0x90D1564: ???
      ==29499==    by 0x50E2E70: (anonymous namespace)::Q_QGS_QSortFilterProxyModelcustomTypesConversionRegistry::innerFunction()::Holder::~Holder() (qsortfilterproxymodel.cpp:494)
      ==29499==    by 0x5B5A120: __run_exit_handlers (exit.c:77)
      ==29499==    by 0x5B5A1A4: exit (exit.c:99)
      ==29499==    by 0x5B3FEAB: (below main) (libc-start.c:294)
      ==29499==  Address 0x90d1564 is not stack'd, malloc'd or (recently) free'd
      ==29499== 
      ==29499== 
      ==29499== Process terminating with default action of signal 11 (SIGSEGV)
      ==29499==  Access not within mapped region at address 0x90D1564
      ==29499==    at 0x90D1564: ???
      ==29499==    by 0x50E2E70: (anonymous namespace)::Q_QGS_QSortFilterProxyModelcustomTypesConversionRegistry::innerFunction()::Holder::~Holder() (qsortfilterproxymodel.cpp:494)
      ==29499==    by 0x5B5A120: __run_exit_handlers (exit.c:77)
      ==29499==    by 0x5B5A1A4: exit (exit.c:99)
      ==29499==    by 0x5B3FEAB: (below main) (libc-start.c:294)
      ==29499==  If you believe this happened as a result of a stack
      ==29499==  overflow in your program's main thread (unlikely but
      ==29499==  possible), you can try to increase the size of the
      ==29499==  main thread stack using the --main-stacksize= flag.
      ==29499==  The main thread stack size used in this run was 8388608.
      ==29499== 
      ==29499== HEAP SUMMARY:
      ==29499==     in use at exit: 10,540 bytes in 60 blocks
      ==29499==   total heap usage: 191 allocs, 131 frees, 30,570 bytes allocated
      ==29499== 
      ==29499== LEAK SUMMARY:
      ==29499==    definitely lost: 16 bytes in 1 blocks
      ==29499==    indirectly lost: 0 bytes in 0 blocks
      ==29499==      possibly lost: 1,488 bytes in 3 blocks
      ==29499==    still reachable: 9,036 bytes in 56 blocks
      ==29499==         suppressed: 0 bytes in 0 blocks
      ==29499== Rerun with --leak-check=full to see details of leaked memory
      ==29499== 
      ==29499== For counts of detected and suppressed errors, rerun with: -v
      ==29499== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
      Segmentation fault (core dumped)
      
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            cnn Qt Core & Network
            stephen.kelly Stephen Kelly (Unused account) (Inactive)
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes