如何了解崩溃的应用程序

时间:2019-08-09 08:45:44

标签: c++ crash sigabrt unhandled-exception unity3d-native-plugins

我在Linux上运行的Unity3D应用程序中遇到了一些烦人的崩溃,我正在使用一个本机插件来渲染2D纹理,而问题很可能与此有关。

我试图禁止使用此类插件,但没有发生崩溃。

#include <stdio.h>
#include "PlatformBase.h"
#include "RenderAPI.h"
#include <cstring>
#include <stdlib.h> 
#include <assert.h>
#include <math.h>
#include "GLEW/glew.h"
#include <ctime>
#include <vector>
#include "CallbackManager.h"
#include <iostream>
#include <mutex>
// #include "GLError.h"
#include <sstream>
#include <string>

struct TextureData
{
    void* g_TextureHandle = NULL;
    void* g_Buffer = NULL;
    int   g_TextureWidth  = 0;
    int   g_TextureHeight = 0;
    int   g_BufferLength = 0;
    void* g_RgbaBuff = NULL;
    FuncCallBack g_Callback = 0;
};

static std::vector<TextureData*> dataList;
static std::mutex dataMutex;
static bool newMode = true;
static int currentIndex = 0;
static FuncPtr log_Callback;


static void LogOut(const char * message)
{
    if(log_Callback)
    {
        std::cout << "Logging to C# " << message << '\n';
        log_Callback(message);
    }
}

extern "C" int UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API CreateTextureData(void* textureHandle, int w, int h, void* rgbaBuffer)
{   
    int result = 0;

    if(currentIndex > 50)
    {
        currentIndex = 0;
        newMode = false;
    }

    if (!newMode)
    {       
        try
        {
            std::lock_guard<std::mutex> lk(dataMutex);
            dataList[currentIndex]->g_TextureHandle = textureHandle;
            dataList[currentIndex]->g_TextureWidth = w;
            dataList[currentIndex]->g_TextureHeight = h;
            dataList[currentIndex]->g_RgbaBuff = rgbaBuffer;
            result = currentIndex;
            currentIndex = currentIndex +1;
        }
        catch(const std::exception& e)
        {
            std::cerr << e.what() << "[NativePluginException]\n";
            std::stringstream ss;
            ss << e.what() << "[NativePluginException]\n";
            std::string s = ss.str();
            LogOut(s.c_str());
        }
    }
    else
    {
        TextureData* tData = new TextureData();
        tData->g_TextureHandle = textureHandle;
        tData->g_TextureWidth = w;
        tData->g_TextureHeight = h;
        tData->g_RgbaBuff = rgbaBuffer;

        std::lock_guard<std::mutex> lk(dataMutex);
        dataList.push_back(tData);
        currentIndex = currentIndex + 1;
        result = dataList.size() - 1;
    }

    return result;
}

extern "C" int UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UpdateTextureData(int dataId, void* buffer, int bufferLength)
{
    try
    {
        if (dataList.size() > dataId) 
        {
            std::lock_guard<std::mutex> lk(dataMutex);
            TextureData *tData = dataList.at(dataId);
            tData->g_Buffer = buffer;
            tData->g_BufferLength = bufferLength;
            return 14;
        }
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << "[NativePluginException]\n";
        std::stringstream ss;
        ss << e.what() << "[NativePluginException]\n";
        std::string s = ss.str();
        LogOut(s.c_str());
    }   

    return 15;
}

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API RemoveTextureData(int dataId)
{

}

static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType);

static IUnityInterfaces* s_UnityInterfaces = NULL;
static IUnityGraphics* s_Graphics = NULL;

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
    s_UnityInterfaces = unityInterfaces;
    s_Graphics = s_UnityInterfaces->Get<IUnityGraphics>();
    s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent);

    // Run OnGraphicsDeviceEvent(initialize) manually on plugin load
    OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize);
}

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload()
{
    s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent);
}


static RenderAPI* s_CurrentAPI = NULL;
static UnityGfxRenderer s_DeviceType = kUnityGfxRendererNull;

static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType)
{
    // Create graphics API implementation upon initialization
    if (eventType == kUnityGfxDeviceEventInitialize)
    {
        assert(s_CurrentAPI == NULL);
        s_DeviceType = s_Graphics->GetRenderer();
        s_CurrentAPI = CreateRenderAPI(s_DeviceType);
    }

    // Let the implementation process the device related events
    if (s_CurrentAPI)
    {
        s_CurrentAPI->ProcessDeviceEvent(eventType, s_UnityInterfaces);
    }

    // Cleanup graphics API implementation upon shutdown
    if (eventType == kUnityGfxDeviceEventShutdown)
    {
        delete s_CurrentAPI;
        s_CurrentAPI = NULL;
        s_DeviceType = kUnityGfxRendererNull;
    }
}

static void ModifyTexturePixelsWithParams(void* textureHandle, int w, int h, void* buffer, int bufferLength, void* rgbaBuffer)
{   
    int textureRowPitch;

    unsigned char * rgba = (unsigned char*)rgbaBuffer;
    unsigned char * buf =  (unsigned char*)buffer;
    if (!buf)
        return;

    int i = 0;
    printf("bufferLength %i width %i height %i \n", bufferLength, w, h);
    if (!textureHandle)
    {
        printf("[NATIVEEXCEPTION]Texture handle was null\n");
        std::stringstream ss;
        ss << "[NATIVEEXCEPTION]Texture handle was null\n";
        std::string s = ss.str();
        LogOut(s.c_str());
        return;
    }

    glBindTexture(GL_TEXTURE_2D, (GLuint)(size_t)textureHandle);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buf);
}

static void UNITY_INTERFACE_API OnRenderEventThreadSafe(int eventID)
{
    try
    {
        if(eventID >= dataList.size())
        {
            printf("EventID bigger than the size of the list %i \n", eventID);          
            return;
        }

        std::lock_guard<std::mutex> lk(dataMutex);
        TextureData *obj = dataList.at(eventID);

        if(obj)
        {
            if(obj->g_TextureHandle && obj->g_Buffer && obj->g_TextureWidth != 0 && obj->g_TextureWidth != 0 && obj->g_BufferLength != 0 && obj->g_RgbaBuff)
            {
                ModifyTexturePixelsWithParams(obj->g_TextureHandle, obj->g_TextureWidth, obj->g_TextureHeight, obj->g_Buffer, obj->g_BufferLength, obj->g_RgbaBuff);
            }
            else
            {
                printf("Can't modify the texture, null element \n");
                std::stringstream ss;
                ss << "[NativePluginException] Can't modify the texture, null element\n";
                std::string s = ss.str();
                LogOut(s.c_str());
            }

            if (obj->g_Callback != 0 && obj->g_Callback)
            {
                obj->g_Callback(eventID);
            }
            else
            {
                printf("Callback to C# was null for id %i \n", eventID);
            }

        }
        else
        {
            printf("Received a null pointer, avoiding the call for eventId %i \n", eventID);
        }
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << "[NativePluginException]\n";
        std::stringstream ss;
        ss << e.what() << "[NativePluginException]\n";
        std::string s = ss.str();
        LogOut(s.c_str());
    }
}

extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFuncThreadSafe()
{
    return OnRenderEventThreadSafe;
}

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SetCallback(int dataId, FuncCallBack callback)
{
    try
    {
        if (dataList.size() > dataId) 
        {
            std::lock_guard<std::mutex> lk(dataMutex);
            TextureData *tData = dataList.at(dataId);
            tData->g_Callback = callback;
        }
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << "[NativePluginException]\n";
        std::stringstream ss;
        ss << e.what() << "[NativePluginException]\n";
        std::string s = ss.str();
        LogOut(s.c_str());
    }
}

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SetLogCallback(FuncPtr callback)
{
    try
    {
        log_Callback = callback;
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << "[NativePluginException]SetLogCallback\n";
        std::stringstream ss;
        ss << e.what() << "[NativePluginException]\n";
        std::string s = ss.str();
        LogOut(s.c_str());
    }   
}

要调用本机插件,我正在在Unity内的纹理GameObject上运行的协程中使用以下代码

while (!exitWhile)
{
    yield return new WaitForEndOfFrame;
    if (shouldRender && !_fakeTexture)
    {
        GL.IssuePluginEvent(GetRenderEventFuncThreadSafe(), textureIndex);
        bufferPointer = IntPtr.Zero;
        if (_doAlphaFading)
            DoAlphaFadeIn();
        else
           color = Color.white;

        shouldRender = false;
        if (!cycleMode) exitWhile = true;
    }
}

纹理创建和更新是在AsyncThread中完成的

textureIndex = CreateTextureData(texturePointer, (int) size.x, (int) size.y, bufferPtr);
[...]
var resp = UpdateTextureData(textureIndex, bufferPtr, buffer.Length);

该插件实际上正在工作,但有时我收到的SIGABRT会使我的应用程序崩溃。 Player.log记录了这样的异常

Receiving unhandled NULL exception
Receiving unhandled NULL exception
#0  0x007f26f55c79c0 in _L_unlock_13
#0  0x007f26e03b59c0 in _L_unlock_13
#1  0x007fff4b896590 in GC_malloc_atomic
#1  0x007f269e00dab0 in mono_threads_detach_coop
#2  0x007f269e00dae0 in mono_threads_detach_coop
#3  0x007f269e00dc30 in mono_threads_detach_coop
#4  0x007f269e00dc90 in mono_threads_detach_coop
#5  0x007f269e00dd90 in mono_threads_set_shutting_down
#6  0x007f269e00de60 in GC_inner_start_routine
#7  0x007f269e00deb0 in GC_call_with_stack_base
#8  0x007f269e00dee0 in start_thread
#2  0x007fff4b8965c0 in mono_gc_register_root
#9  0x007f269e00df80 in clone
#3  0x007fff4b8965e0 in mono_class_vtable
#4  0x007fff4b896600 in mono_string_chars
#5  0x007fff4b896620 in mono_string_new_utf16
#6  0x007fff4b896660 in mono_string_new_len
#7  0x007fff4b8966f0 in operator delete(void*)
#8  0x007fff4b896710 in operator delete(void*)
#9  0x007fff4b896720 in std::vector<std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > >, std::allocator<std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > > >::~vector()

我也设法获得了strace日志,该日志非常大,因此我将其上传到了保管箱文件:https://www.dropbox.com/s/gwfo7alpbkp5c13/strace.log?dl=0

我不是c ++专家,所以我不知道我的本机插件中的某些内容是否会导致类似这种情况。

在此先感谢任何会回答的人!

0 个答案:

没有答案