EtoCollapsibleSection crashes Rhino

Hi,

Came across this weird issue today…

I’ve been following the examples on Github (specifically, https://github.com/mcneel/rhino-developer-samples/tree/6/rhinocommon/cs/SampleCsCustomRenderSettingsSections) and copypasting the render settings section classes to my own plug-in.

It seems that either the newer versions of Rhino don’t like the example, or I am missing something very obvious. I’ve trimmed down the problem to RenderSettingsCustomSections(List<ICollapsibleSection> sections) and when my custom section gets added. The snippet from the plug-in class looks like this:

    private CustomRenderSettingsSection m_render_section;
    
    public CustomPlugIn()
    {
        if (Instance == null) Instance = this;
        m_render_section = new CustomRenderSettingsSection();
    }

    public override void RenderSettingsCustomSections(List<ICollapsibleSection> sections)
    {
        sections.Add(m_render_section);
        //base.RenderSettingsCustomSections(sections);
    }

Commenting out sections.Add(m_render_section); makes it work.

The problem appears when I attempt to turn on the Rendering panel in Rhino, when my custom render plug-in is active. Rhino freezes and eventually crashes.

I’ve pared down the CustomRenderSettingsSection class to the minimum, meaning getting rid of all the event handlers and usage of the CustomRenderSettingsViewModel, to try to narrow down the problem.

CustomRenderSettingsSection inherits from EtoCollapsibleSection and combines CustomSection and CustomRenderSettingsSection from the Github example.

Does it need the ViewModel class in order to work?

Much thanks,

Tom

After further poking around, the same problem seems to arise in the SampleCsCustomSunSections example (https://github.com/mcneel/rhino-developer-samples/tree/6/rhinocommon/cs/SampleCsCustomSunSections).

Creating a basic CustomSection object and adding it to the sun section with SunCustomSections(List<ICollapsibleSection> sections) in the main plug-in class crashes Rhino when you attempt to visit the Sun panel.

Perhaps an Eto problem? Both inherit from EtoCollapsibleSection.

I tried the SampleCsCustomSunSections and it works for me. However I used the latest code and debug build which could affect the issue.

I have some questions which could hopefully help to solve the problem.

When Rhino crashes do you get a crash dump that we could look at? Also which Rhino release version are you running? I would like to test the SampleCsCustomSunSections sample against the same version as you have.

I will also ask a few here in the office to test and see if they are able to get it to crash.

Hi Max,

Thanks a lot for looking into this.

I’m using the latest automatic update of Rhino (6.9.18271.20591, 09/28/2018). The plug-in is using RhinoCommon 6.8.18240.20051 via Nuget. The same problem occurs on a different computer, with - I think - a previous build of Rhino 6.

The Windows crash dialog (“This program is not responding…”) mentions a stack overflow exception so it sounds like there’s a nasty loop somewhere in there. I couldn’t find a .dmp file from the crash, unfortunately, unless it’s hiding in some other place?

I have also tried declaring and instantiating the new section within the RenderSettingsCustomSections instead of making it a member of the plugin class, and have tried leaving out the base class call, to no effect:

public CustomPlugIn()
{
    if (Instance == null) Instance = this;
}

public override void RenderSettingsCustomSections(List<ICollapsibleSection> sections)
{
    var m_render_section = new CustomRenderSettingsSection();
    sections.Add(m_render_section);
    base.RenderSettingsCustomSections(sections);
}

Otherwise, I’m not sure how else to narrow down the problem…

The custom render section class looks like this. CustomSection is the right from the SampleCs examples.

public class CustomRenderSettingsSection: CustomSection
{
    private Button m_button;
    private CheckBox m_checkbox;
    private Label m_button_lb;
    private Label m_checkbox_lb;
    private Label m_button_clicks_lb;
    private Label m_checkbox_value_lb;
    private int m_clicks;
    private LocalizeStringPair m_caption;

    public CustomRenderSettingsSection()
    {
        m_caption = new LocalizeStringPair("CustomRender", "CustomRender");
        InitializeComponents();
        InitializeLayout();
        RegisterControlEvents();

    }

    public override LocalizeStringPair Caption
    {
        get
        {
            return m_caption;
        }
    }
    
    public override int SectionHeight
    {
        get
        {
            return 80;
        }
    }

    private void InitializeComponents()
    {
        m_clicks = 0;

        m_button = new Button()
        {
            Text = "Button"
        };

        m_checkbox = new CheckBox();

        m_button_lb = new Label()
        {
            Text = "",
            VerticalAlignment = VerticalAlignment.Center,
            Width = 20
        };

        m_checkbox_lb = new Label()
        {
            Text = "",
            VerticalAlignment = VerticalAlignment.Center,
            Width = 20
        };

        m_button_clicks_lb = new Label()
        {
            Text = "Number of clicks: ",
            VerticalAlignment = VerticalAlignment.Center,
        };

        m_checkbox_value_lb = new Label()
        {
            Text = "Custom User Data",
            VerticalAlignment = VerticalAlignment.Center,
        };

        m_checkbox_lb.Text = m_checkbox.Checked.ToString();
        m_button_lb.Text = m_clicks.ToString();

    }

    private void InitializeLayout()
    {
        TableLayout layout = new TableLayout()
        {
            // Padding around the table
            Padding = 10,
            // Spacing between table cells
            Spacing = new Eto.Drawing.Size(15, 15),
            Rows =
            {
                new TableRow(m_button_clicks_lb, m_button_lb, m_button),
                new TableRow(m_checkbox_value_lb, m_checkbox, m_checkbox_lb)
            }
        };
        Content = layout;
    }

    private void RegisterControlEvents()
    {
        m_checkbox.CheckedChanged += OnCheckedChanged;
        m_button.Click += OnButtonClick;
    }

    private void UnRegisterControlEvents()
    {
        m_checkbox.CheckedChanged -= OnCheckedChanged;
        m_button.Click -= OnButtonClick;
    }

    private void OnLoadComplete(object sender, EventArgs e)
    {
    }

    private void OnCheckedChanged(object sender, EventArgs e)
    {
        m_checkbox_lb.Text = m_checkbox.Checked.ToString();

        if (m_checkbox.Checked != null)
        {
            bool checked_state = (bool)m_checkbox.Checked;
        }
    }

    private void OnButtonClick(object sender, EventArgs e)
    {
        m_clicks++;
        m_button_lb.Text = m_clicks.ToString();
    }
    
}

Hi again Max,

After some debugging, looks like this is what’s causing problems:

Rhino.UI.dll!Rhino.UI.Controls.EtoCollapsibleSection.Rhino.UI.Controls.IWindow.Parent.set(System.IntPtr value)

It just loops until it blows the stack. Is there somewhere where I am not setting the correct Eto panel parent or something?

Hi @tom_svilans,

You should not need to worry about setting the Parent. Rhino should take care of all this. This crash seems to be harder then I expected.

I tried to build the SampleCsCustomSunSections against 6.8.18240.20051 and then load the plugin in Rhino 6.9.18271.20591, but I was not able to get the crash.

Is it possible to get the call stack for further investigation?

Best Regards,
Max

One more question: Did this work before or is this the first time you tried to create a custom render section? Thinking about the option if some recent change has broken the custom sections.

Call stack looks like this:

[Managed to Native Transition]		 
Rhino.UI.dll!Rhino.UI.Controls.EtoCollapsibleSection.Rhino.UI.Controls.IWindow.Parent.set(System.IntPtr value)	Unknown
...
Rhino.UI.dll!Rhino.UI.Controls.EtoCollapsibleSection.Rhino.UI.Controls.IWindow.Parent.set(System.IntPtr value)	Unknown
The maximum number of stack frames supported by Visual Studio has been exceeded.	

where ... is just the same line over and over again. Not too informative :wink:

I only tried recently to create a custom render section.

The very strange thing is that I got the example project to work, but not my plug-in, even after copying the exact same code over. Even then, the example project sometimes chooses not to work, and I’m trying to find out why that is.

I did notice that when the CustomSection ID is changed to something other than private Guid m_uuidPlugIn = new Guid("54cc4233-7407-4c76-9422-0b6f01ca802a");, the section doesn’t show up in the render settings in Rhino. Is that a hardcoded Guid in Rhino?

I could package up both projects and send them to you, if it helps?

That is a good question as that does not seem to be documented well. That uuid should be the Plug-in uuid

It should be the same as the

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid(“54cc4233-7407-4c76-9422-0b6f01ca802a”)] // This will also be the Guid of the Rhino plug-in

Which is found in the AssemblyInfo.cs of your plugin-in project

kuva

The code in the CustomSection should not redefine the guid, it should return directly the Guid defined in the AssemblyInfo as this will cause problems. I think I wrote the CustomSection Sample :). Not sure how to do it directly at the moment, but we should fix it.

private Guid m_uuidPlugIn = new Guid("54cc4233-7407-4c76-9422-0b6f01ca802a");

public override Guid PlugInId
{
  get { return m_uuidPlugIn; }
}

You should change the Guid m_uuidPlugIn to be the same as the uuid in the AssemblyInfo.cs file of your plugin-in project.

Yes I can try to debug what happens in Rhino using your packages.

Ah this sounds crucial. I’ll try that out in a minute.

For now, I tried uninstalling the RhinoCommon Nuget package and instead referencing RhinoCommon, Rhino.UI, and Eto directly from the Rhino folder. It doesn’t seem to crash now, but the section doesn’t show up yet, but that’s maybe due to the Guid issue.

Ok, can confirm that it now shows up when using the plug-in Guid :slight_smile:

When switching back to using the Nuget package instead of directly referencing the DLLs, it once again crashes with a StackOverflowException as before.

So it seems like it may be related to the Nuget package. Same result even when using the most up-to-date Nuget package.

Thanks for the information. This explains why i could not reproduce it. The sample projects I have reference the C:\Program Files\Rhino 6\System\ folder where I have the RhinoCommon, Rhino.UI and Eto references of the latest commerical build installed on my computer.

The problem is clearly with the nuget. The RhinoCommon nugget. (RhinoCommon SDK for Rhino WIP for Windows) I will install it and see what is wrong, but great to hear that the problem is under control.

Thanks for your help!

Maybe, in the examples, you could put a comment about the assembly / plug-in Guid, as this was not obvious (to me, at least). Now it seems to work OK.

The section will show up when your renderer is set as the current renderer. This specific section for render settings is meant for render plug-ins. If your renderer isn’t active your section shouldn’t show, either.

Hi Nathan,

Yes, it’s a render plug-in and now it works as supposed to. It just wasn’t clear that the PlugInId property in the EtoCollapsibleSection subclass had to refer to the main plug-in Guid defined in AssemblyInfo.cs, as it was hard-coded in the example files.

Now on to the next set of bugs :slight_smile:

Tom

This crash (RH-50349) is fixed in the latest Service Release Candidate.

Thanks, @dan!