首页 > c# > SIGABRT抛出xamarin在模型c#中形成自定义getter / setter

SIGABRT抛出xamarin在模型c#中形成自定义getter / setter (SIGABRT thrown xamarin forms custom getter/setter in model c#)

问题

**

注意; 21-12-2018 - 更改了问题的名称以符合此问题的新实例。有关这方面的信息位于底部。

**

我一直在努力解决这个错误3周,尝试了我能想到的一切,甚至重新安装了2017年的Visual Studio。

首先是一些背景故事;

我正在开发一个应用程序,可以订购三明治,并完成大部分重要功能。整个订购流程在过去的4个月里一直在运作。几个星期前,有一个灾难周,一个被烧毁的保险丝盒导致停电。这不知何故打破了防火墙,整个公司网络都崩溃了。在安装android工作室期间(与visual studio / xamarin一起)。几天后,视觉工作室2017的更新出错了,我做了一个完整的重新安装并删除了android工作室。然后错误开始出现。

大多数应用程序仍然可以正常工作,您可以登录,检查篮子,浏览类别等;但是; 当在REST实现中调用特定函数时,app关闭,调试器显示致命信号6 SIGABRT -6错误。

12-07 12:57:29.409 F /(20795):*断言/Users/builder/jenkins/workspace/xamarin-android-d15-9/xamarin-android/external/mono/mono/mini/unwind.c: 640,条件`cfa_reg!= -1'未满足

12-07 12:57:29.409 F / libc(20795):致命信号6(SIGABRT),tid 20828中的代码-6(线程池Wor),pid 20795(e.Appnamehere)

代码如下:

public async Task<ObservableCollection<T>> GetAllWithId<T>(Guid id)
{
    var t = typeof(T);
    var uri = GetURI<T>();
    ObservableCollection<T> oc = new ObservableCollection<T>();
    try
    {
        var tmpUri = "";
        // IF statements to determine URI, if no ifs succeed let run and catch exception.. ps. can be changed for typeswitch
        if (typeof(T) == typeof(Product)) { tmpUri = uri + "/incategory/" + id; }/*use category id inside*/
        if (typeof(T) == typeof(Order)) { tmpUri = uri + "/fromuser/" + id; }/*use user id*/
        var client = GetNewClient();
        using (client)
        {
            HttpResponseMessage result = await client.GetAsync(tmpUri);
            if (result.IsSuccessStatusCode)
            {
                var content = await result.Content.ReadAsStringAsync();
                Debug.WriteLine(content);             
                oc = JsonConvert.DeserializeObject<ObservableCollection<T>>(content);// <<<<<< SIGABRT THROWN HERE
                //* Assertion at /Users/builder/jenkins/workspace/xamarin-android-d15-9/xamarin-android/external/mono/mono/mini/unwind.c:640, condition `cfa_reg != -1' not met
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine(@"ERROR {0}", ex.Message);
    }

    return oc;
}

有一个实现使用所有控制器使用的泛型。方法getURIgetNewClient分别做构建URI到相应的类型并返回一个客户端实例。

自开发以来,xamarin核心和其他软件包尚未更新,因为这通常会破坏内容。所有软件包的当前版本与开发开始时(即没有错误时)相同。(底部的包和版本列表)。

该错误在newtonsoft.json软件包的最后两个版本上执行(错误从v11.0.2开始,然后我更新到v12.0.1,错误仍然发生)。API数据从预期中检索并按预期工作,并以正确的格式返回数据。调试器没有显示堆栈跟踪,但确实说错误通常是由本机单声道代码或依赖项使用的本机代码引起的。

如果有人需要更多信息,我会很乐意提供它,因为我无法在谷歌上找到任何关于如何解决这个问题。

错误也发生在所有仿真器上(范围从512mb到2gb ram,不同的堆大小和不同的渲染器。我无法使用物理设备进行测试,因为网络仍然处于锁定状态,并且设备无法连接)

版本信息

更新; 它是固定的(我认为)。20-12-2018

我明确地在API端构建对象并将它们作为对应类型的对象(即产品,订单等)而不是var发送。

在反序列化,重新序列化和重复之后,我最终得到了一个有效但效率极低的解决方案。

接下来,我在模型上的属性上剪切了几个自定义getter和setter。(这绝不是此问题的指定原因,但它有助于修复它。)

它仍然有效,然后我尝试使用问题中显示的原始代码行,这是有效的。

注意,我确实重新安装了Visual Studio两次..(一次从15.9.2更新到15.9.3,昨天卸载并安装了新的更新,15.9.4)。

这是在较旧的分支上完成的,该分支仍然具有所有依赖项的原始版本。

总而言之,此错误不应由不匹配的反序列化对象中的错误引起。这样的错误应该作为反序列化错误或类似的东西抛出,而不是抛出本机单声道展开错误。

(导致此错误的代码行被两个嵌套的try-catch块包围..)

更新..它再次发生在 21-12-2018

所以错误昨天消失了。我希望它是好的,但现在又重新发生了。我将其缩小到产品型号。(因为在加载产品时和加载历史订单时发生了原始错误,这些订单只共享相同的API方法,它必须在那里,它也是如此)。

抛出相同的错误,除了现在历史订单仍然有效,除了产品没有。它发生在我为我的模型添加了一个自定义的getter和setter。代码如下;

public Object ProductImage {
             get { return ProductImage; }
             set {

                try
                {
                    if (value.ToString().Contains("/api/DynamicImages/getimageonly/"))
                    {
                        string imreBase64Data = Convert.ToBase64String(Constants.ObjectToByteArray(value));
                        ProductImage = string.Format("data:image/png;base64,{0}", imreBase64Data);
                    }
                    else
                    {
                        ProductImage = value;
                    }


                }
                catch (Exception ex) { ProductImage = value; }


            }
           //   get;set;//<-- when i use this instead no signal abort is thrown but the images wont load when they are retrieved as either a file or data from my own API. (images retrieved as link to external site still work, falling back to place holders still works too.)
        }

当我恢复到简单的get; set; 有用。任何接受者?注意; 我更新了问题的名称,以更具体地解决这个新问题。

解决方法

根本原因是不间断的递归调用。
例如:
ProductImage = value - >它将再次触发调用setter。
结果,一次又一次地调用了setter。

在java中,它会报告此类情况下的stackoverflow错误。
但是,在单声道中,它显示了这样的错误消息,这对于调试来说并不清楚。

解决方案是:

private Object _productImage;
public Object ProductImage {
    get { return _productImage; }
    set {
    ... 
    _productImage = {some value};
    }
}

问题

**

Notice; 21-12-2018 - changed the name of the question to be in line with new instance of this problem. Information regarding this is at the bottom.

**

I have been struggling with this error for 3 weeks now, tried everything I could think of, even reinstalling visual studio 2017.

First a bit of backstory;

I'm developing an app in which sandwiches can be ordered and most of the important features are finished. The entire ordering process has been working for the past 4 months. A couple of weeks ago there was kind of a disaster week, a blown out fusebox which caused a power outage. This somehow broke the firewall and the whole company network went down. During the installation of the android studio (alongside visual studio/xamarin). A couple of days later an update of visual studio 2017 went awry and I did a complete reinstall and removed android studio. Then the errors started showing up.

Most of the app still works fine, you can log in, check baskets, browse categories etc. however; when a specific function is called in the REST implementation the app shuts down and the debugger shows a Fatal signal 6 SIGABRT -6 error.

12-07 12:57:29.409 F/ (20795): * Assertion at /Users/builder/jenkins/workspace/xamarin-android-d15-9/xamarin-android/external/mono/mono/mini/unwind.c:640, condition `cfa_reg != -1' not met

12-07 12:57:29.409 F/libc (20795): Fatal signal 6 (SIGABRT), code -6 in tid 20828 (Thread Pool Wor), pid 20795 (e.Appnamehere)

Code below:

public async Task<ObservableCollection<T>> GetAllWithId<T>(Guid id)
{
    var t = typeof(T);
    var uri = GetURI<T>();
    ObservableCollection<T> oc = new ObservableCollection<T>();
    try
    {
        var tmpUri = "";
        // IF statements to determine URI, if no ifs succeed let run and catch exception.. ps. can be changed for typeswitch
        if (typeof(T) == typeof(Product)) { tmpUri = uri + "/incategory/" + id; }/*use category id inside*/
        if (typeof(T) == typeof(Order)) { tmpUri = uri + "/fromuser/" + id; }/*use user id*/
        var client = GetNewClient();
        using (client)
        {
            HttpResponseMessage result = await client.GetAsync(tmpUri);
            if (result.IsSuccessStatusCode)
            {
                var content = await result.Content.ReadAsStringAsync();
                Debug.WriteLine(content);             
                oc = JsonConvert.DeserializeObject<ObservableCollection<T>>(content);// <<<<<< SIGABRT THROWN HERE
                //* Assertion at /Users/builder/jenkins/workspace/xamarin-android-d15-9/xamarin-android/external/mono/mono/mini/unwind.c:640, condition `cfa_reg != -1' not met
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine(@"ERROR {0}", ex.Message);
    }

    return oc;
}

There is one implementation using generics used by all controllers. The methods getURI and getNewClient respectively do build the URI to the corresponding type and returning a client instance.

Since the start of development, the xamarin core and other packages have not been updated since this usually breaks stuff. The current versions of all packages are the same as when development began (i.e. when there were no errors). (list of packages and versions at the bottom).

The error performs on the last 2 versions of the newtonsoft.json packages (error started at v11.0.2, then i updated to v12.0.1, the error still occurs). The API data is retrieved from and works as intended and returns the data in the correct format. The debugger shows no stack trace but does say that the error usually is caused by native mono code or native code used by dependencies.

If anyone needs more info I'll be glad to provide it since I haven't been able to find anything on google on how to fix this.

The error also occurs on all emulators (ranging from 512mb to 2gb ram, varying heap sizes and varying renderers. I am unable to test with a physical device because the network is still in lockdown and somehow the device cannot connect)

VersionInformation

Update; it's fixed (I think). 20-12-2018

I explicitly build the objects on the API side and send them as an object of their corresponding type (i.e. Product, Order etc.) instead of var.

After deserializing, reserializing and repeating that once more, i ended up with a working but grossly inefficient solution.

Following that, I cut a couple of custom getters and setters on properties on the models. (This is by no means a designated cause of this issue, but it helped fix it. )

It still worked, I then tried to use the original line of code as displayed in the question, which worked.

Note, I did re-install visual studio twice..(once when updating from 15.9.2 to 15.9.3, and yesterday uninstalled it and installed it with the new update, 15.9.4).

This is done on an older branch which still has the original versions of all dependencies.

All in all, this error should not be caused by errors in unmatching deserialization objects. Such an error should be thrown as a Deserialization error or something alike, not throw a native mono unwind error.

(The line of code that causes this error is surrounded by two nested try-catch blocks..)

Update.. it happened again 21-12-2018

So the error disappeared yesterday. I hoped it was for good, but now it re-occurred. I narrowed it down to the product model. (since the original error occurred when loading products and when loading historic orders, which only shared the same API method, it had to be there, and it was too).

The same error is thrown, except now the historic orders still work, except the products do not. It happened when i added a custom getter and setter to my model. code below;

public Object ProductImage {
             get { return ProductImage; }
             set {

                try
                {
                    if (value.ToString().Contains("/api/DynamicImages/getimageonly/"))
                    {
                        string imreBase64Data = Convert.ToBase64String(Constants.ObjectToByteArray(value));
                        ProductImage = string.Format("data:image/png;base64,{0}", imreBase64Data);
                    }
                    else
                    {
                        ProductImage = value;
                    }


                }
                catch (Exception ex) { ProductImage = value; }


            }
           //   get;set;//<-- when i use this instead no signal abort is thrown but the images wont load when they are retrieved as either a file or data from my own API. (images retrieved as link to external site still work, falling back to place holders still works too.)
        }

When I revert to a simple get;set; it works. Any takers? Note; I updated the name of the question to be more specific for this new issue.

解决方法

the root cause is non-stop recursive call.
such as:
ProductImage = value -> it will trigger call setter again.
as a result, setter is called again and again.

in java, it will report stackoverflow error for such case.
however, in mono, it show such error message, which is not clear for debug.

the solution is:

private Object _productImage;
public Object ProductImage {
    get { return _productImage; }
    set {
    ... 
    _productImage = {some value};
    }
}
相似信息