DD-L / lproxy

8 stars 3 forks source link

Android release: F libc : Fatal signal 7 (SIGBUS), code 1 #166

Open DD-L opened 8 years ago

DD-L commented 8 years ago

qt for android release gcc

问题:

包含 store.lockfree.queue, 用 qt 5.5.1 编译 android release 版本的程序,在运行时就会出现:

F libc    : Fatal signal 7 (SIGBUS), code 1, fault addr 0x9da51154 in tid 25836 (.example.lproxy)
"org.qtproject.example.lproxy" died.

此时,程序尚未进入 qt.main 函数, 看来是全局区(静态区)出了问题。但是 编译 debug 版本的 android 程序,则运行正常,很奇怪的现象。其他平台:win32/linux 不管是 debug 还是 release 也都不会出现这个问题。

qt android release 的 gcc 编译指令示例:

D:\Qt\android\android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++  \
-c -Wno-psabi \
-march=armv7-a -mfloat-abi=softfp -mfpu=vfp -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums \
-DANDROID -Wa,--noexecstack -fno-builtin-memmove \
-std=c++11 -pthread -O2 -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -mthumb \ 
-Wall -Wno-psabi -W -D_REENTRANT -fPIC -DLOG_LOCKFREE_QUEUE -D_REENTRANT -DBOOST_REGEX_NO_LIB -DBOOST_DATE_TIME_SOURCE -DBOOST_SYSTEM_NO_LIB -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_WEBSOCKETS_LIB -DQT_NETWORK_LIB -DQT_WEBCHANNEL_LIB -DQT_CORE_LIB -I../lproxy-local-test -I. -I../lproxy-local-test/lproxy/contrib/boost/boost_1_57_0 -I../lproxy-local-test/lproxy/contrib/cryptopp -I../lproxy-local-test/lproxy/src/core -I../lproxy-local-test/lproxy/src/core/boost_build -ID:/Qt/QtDev/5.5/android_armv7/include -ID:/Qt/QtDev/5.5/android_armv7/include/QtQuick -ID:/Qt/QtDev/5.5/android_armv7/include/QtGui -ID:/Qt/QtDev/5.5/android_armv7/include/QtQml -ID:/Qt/QtDev/5.5/android_armv7/include/QtWebSockets -ID:/Qt/QtDev/5.5/android_armv7/include/QtNetwork -ID:/Qt/QtDev/5.5/android_armv7/include/QtWebChannel -ID:/Qt/QtDev/5.5/android_armv7/include/QtCore -I. -isystem D:/Qt/android/android-ndk-r10e/sources/cxx-stl/gnu-libstdc++/4.9/include -isystem D:/Qt/android/android-ndk-r10e/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include -isystem D:/Qt/android/android-ndk-r10e/platforms/android-9/arch-arm/usr/include -ID:/Qt/QtDev/5.5/android_armv7/mkspecs/android-g++ -o websocketclientwrapper.obj ../lproxy-local-test/websocketchannel/websocketclientwrapper.cpp

debug 是没问题的:

D:\Qt\android\android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ \
-c -Wno-psabi \
-march=armv7-a -mfloat-abi=softfp -mfpu=vfp -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums \
-DANDROID -Wa,--noexecstack -fno-builtin-memmove \
-std=c++11 -pthread -g -g -marm -O0 -fno-omit-frame-pointer \
-Wall -Wno-psabi -W -D_REENTRANT -fPIC -DLOG_LOCKFREE_QUEUE -D_REENTRANT -DBOOST_REGEX_NO_LIB -DBOOST_DATE_TIME_SOURCE -DBOOST_SYSTEM_NO_LIB -DQT_QML_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_WEBSOCKETS_LIB -DQT_NETWORK_LIB -DQT_WEBCHANNEL_LIB -DQT_CORE_LIB -I../lproxy-local-test -I. -I../lproxy-local-test/lproxy/contrib/boost/boost_1_57_0 -I../lproxy-local-test/lproxy/contrib/cryptopp -I../lproxy-local-test/lproxy/src/core -I../lproxy-local-test/lproxy/src/core/boost_build -ID:/Qt/QtDev/5.5/android_armv7/include -ID:/Qt/QtDev/5.5/android_armv7/include/QtQuick -ID:/Qt/QtDev/5.5/android_armv7/include/QtGui -ID:/Qt/QtDev/5.5/android_armv7/include/QtQml -ID:/Qt/QtDev/5.5/android_armv7/include/QtWebSockets -ID:/Qt/QtDev/5.5/android_armv7/include/QtNetwork -ID:/Qt/QtDev/5.5/android_armv7/include/QtWebChannel -ID:/Qt/QtDev/5.5/android_armv7/include/QtCore -I. -isystem D:/Qt/android/android-ndk-r10e/sources/cxx-stl/gnu-libstdc++/4.9/include -isystem D:/Qt/android/android-ndk-r10e/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include -isystem D:/Qt/android/android-ndk-r10e/platforms/android-9/arch-arm/usr/include -ID:/Qt/QtDev/5.5/android_armv7/mkspecs/android-g++ -o webchannelobject.obj ../lproxy-local-test/webchannelobject/webchannelobject.cpp

release 和 debug 链接指令相同。

最终定位到问题代码 store.h

#include <boost/lockfree/queue.hpp>
template <typename T>
class Store<T, boost::lockfree::queue<T> > : 
        public boost::serialization::singleton<
                    Store<T, boost::lockfree::queue<T> > >,
        public boost::lockfree::queue<T> {
public:
    //using boost::lockfree::queue<T>::push;
    //using boost::lockfree::queue<T>::pop;
    typedef boost::lockfree::queue<T> BASETYPE;

    bool push(const T* element_ptr) {
        if (element_ptr) {
            return this->push(*element_ptr);
        }
        else {
            return false;
        }
    }
    bool push(const T& element) {
        return BASETYPE::push(element);
    }

    bool pop(T* element_ptr) {
        if (element_ptr) {
            return this->pop(*element_ptr);
        }
        else {
            return false;
        }
    }
    bool pop(T& element) {
        return BASETYPE::pop(element);
    }

    // 继承父类的reserve
    //void reserve(size_t);
    //void reserve_unsafe(size_t);
protected:
    Store(size_t _capacity = __STORECAPACITY__s) :
        boost::lockfree::queue<T>(_capacity) {}
    Store(const Store&) {}
private:
    // 屏蔽下面接口
    size_t size() const { return 0; }  
    bool full()   const { return false; }
};

对两个基类虚继承也照旧同一个问题。

gcc 版本

D:\Qt\android\android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ --version

arm-linux-androideabi-g++ (GCC) 4.9 20140827 (prerelease)
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Android 版本:

Android 6.0 ABI:armeabi-v7a

解决办法:去掉 public boost::serialization::singleton<Store<T, boost::lockfree::queue<T> > > , 改用单继承。

更深层次的原因不详,有可能和 boost::serialization::singleton 有关,也可能和 boost::lockfree 有关,也可能和内存字节对齐有关。

DD-L commented 8 years ago

但是 https://github.com/DD-L/lproxy/commit/3b3df594fc51207bd758bf700ec0f6879f968a64 这样修改后 Qt android arm release 版本是好了,但是 Qt android arm debug 版本就又出现同样的问题。真是好奇怪的现象!!!日了狗了。。。

DD-L commented 8 years ago

再一次用下面代码尝试:

namespace __store_private_ {
static const size_t STORECAPACITY = 2000000; // default capacity of Store
}

#include <type_traits>
#include <boost/lockfree/queue.hpp>
#include <boost/lockfree/stack.hpp>

namespace __store_private_ {

template <typename T, typename U>
class lock_free_base {
static_assert(std::is_same<boost::lockfree::queue<U>, T>::value ||
              std::is_same<boost::lockfree::stack<U>, T>::value,
"T must be 'boost::lockfree::queue<some_type>' "
"or 'boost::lockfree::stack<some_type>'");
protected:
    lock_free_base(std::size_t n) : _store(n) {}
    virtual ~lock_free_base() {}
public:
    bool is_lock_free(void) const {
        return _store.is_lock_free();
    }

    void reserve(std::size_t n) {
        _store.reserve(n);
    }

    void reserve_unsafe(std::size_t n) {
        _store.reserve_unsafe(n);
    }

    bool empty(void) const {
        return _store.empty();
    }

    bool push(const U* element_ptr) {
        if (element_ptr) {
           return this->push(*element_ptr);
        }
        else {
           return false;
        }
    }
    bool push(const U& element) {
        return _store.push(element);
    }

    bool pop(U* element_ptr) {
        if (element_ptr) {
            return this->pop(*element_ptr);
        }
        else {
            return false;
        }
    }
    bool pop(U& element) {
        return _store.pop(element);
    }

    bool bounded_push(U const& e) {
        return _store.bounded_push(e);
    }
    bool unsynchronized_push(U const& e) {
        return _store.unsynchronized_push(e);
    }

    bool unsynchronized_pop(U & e) {
        return _store.unsynchronized_pop(e);
    }
protected:
    T _store;
}; // class lock_free_base

} // namespace __store_private_

// class Store 对 boost::lockfree::queue 偏特化版本
// defaults to boost::lockfree::fixed_sized<false>  , Dynamic Size
template <typename T>
class Store<T, boost::lockfree::queue<T> > :
    //public boost::serialization::singleton<
    //    Store<T, boost::lockfree::queue<T> > >,
    public
    __store_private_::lock_free_base<boost::lockfree::queue<T>, T>
{
public:
    static Store& get_mutable_instance(void) {
        static Store __store;
        return __store;
    }

    static const Store& get_const_instance(void) {
        return Store::get_mutable_instance();
    }
protected:
typedef __store_private_::lock_free_base<boost::lockfree::queue<T>, T>\
        BASETYPE;
    //Store(size_t _capacity = __store_private_::STORECAPACITY)
    Store(size_t _capacity = 0)
          : BASETYPE(_capacity) {}
    Store(const Store&) = delete;
};

// class Store 对 boost::lockfree::stack 偏特化版本
// defaults to boost::lockfree::fixed_sized<false>  , Dynamic Size
template <typename T>
class Store<T, boost::lockfree::stack<T> > :
    //public boost::serialization::singleton<
    //    Store<T, boost::lockfree::stack<T> > >,
    public
    __store_private_::lock_free_base<boost::lockfree::stack<T>, T>
{
public:
    static Store& get_mutable_instance(void) {
        static Store __store;
        return __store;
    }

    static const Store& get_const_instance(void) {
        return Store::get_mutable_instance();
    }
protected:
typedef __store_private_::lock_free_base<boost::lockfree::stack<T>, T>\
        BASETYPE;
    //Store(size_t _capacity = __store_private_::STORECAPACITY)
    //Store(size_t _capacity = 0)
          : BASETYPE(_capacity) {}
    Store(const Store&) = delete;
};

发现还是有问题:

第一次 测试 Qt Android arm release 可以,第二次 测试 Qt Android arm debug 也可以,第三次 测试 Qt Android arm release 又狗带了!!!!(忘记测试期间修改什么东西了)第四次测试 Qt Android arm debug 仍然可以。

整个人都不好了,被这个 bug 彻底整崩溃了。

调用处代码摘要:

class LogStore_lockfree {
public:
        LogStore_lockfree(void) 
            : m_logstore(__Log_Store::get_mutable_instance()) {}
        LogStore_lockfree(const LogStore_lockfree&) = delete;
        LogStore_lockfree& operator=(const LogStore_lockfree&) = delete;
    private:
        typedef Store<LogVal*, boost::lockfree::queue<LogVal*> > __Log_Store;
        __Log_Store&                                             m_logstore;
};

有可能是 引用成员变量 的原因,放弃追踪了。

因为还有其他最优的解决办法可以彻底规避此问题: 裸用 boost::lockfree,并放弃使用引用

        LogStore_lockfree(void)
            : m_logstore(__store_private_::STORECAPACITY) {}
        LogStore_lockfree(const LogStore_lockfree&) = delete;
        LogStore_lockfree& operator=(const LogStore_lockfree&) = delete;
    private:
        typedef boost::lockfree::queue<LogVal*>  __Log_Store;
        __Log_Store                              m_logstore;

酱,所有问题都烟消云散了。

DD-L commented 8 years ago

See https://github.com/DD-L/lproxy/commit/0fc833b0f88ca4c0f997f61ed4c144627d129af2