eclipse / swtchart

Eclipse Public License 2.0
43 stars 41 forks source link

Resource leak in the Chart when the parent is disposed before the chart itself. #372

Closed raghucssit closed 5 months ago

raghucssit commented 7 months ago

Problem: We can create a chart on a shell on any composite on eclipse views. A shell can be opened from eclipse platform in the form of dialog/Any view can be populated and closed. Use cases are like showing some data chart on a separate window/view. User can usually close Window/View. In this case a View is disposed first and subsequently Chart as well.This Chart disposal does not invoke Chart.dispose(). Any later atempt to dispose the chart does not clear below resources if(!isDisposed()) { title.dispose(); legend.dispose(); axisSet.dispose(); super.dispose(); }.

Work around seems to be adding the dispose listener to parent and dispose the chart. Or adding the dispose listener to chart and dispose the resources.

raghucssit commented 7 months ago

This issue is introduced after this https://github.com/eclipse/swtchart/issues/289 There are cases where chart is disposed and it's children are not which I mentioned above.

eselmeister commented 7 months ago

@raghucssit Thanks for reporting it. Could you create a demo to show this case, like: org.eclipse.swtchart.extensions.examples.charts.DemoChart.java

iloveeclipse commented 7 months ago

If I remember right, the problem is observed in the code of a view (not editor like in #289) that is being closed. In this case, the parent control given to view on createPartControl() is disposed early and also disposes all created children - so that the actual dispose() method of the chart is called on already disposed chart object, so it can't dispose created objects.

eselmeister commented 7 months ago

Yep, we see it from time to time, especially when closing applications. Anyways, as soon as we figured out how to reproduce it, we are able to write a fix.

raghucssit commented 7 months ago

bar-chart-view.zip Please import this plugin and launch a new run time from the plugin. Open the view "Bar Chart View", a bart can be seen. Then close the view we can see resource leak.

Below View class can reproduce the issue.

` public class BarChartView extends ViewPart {

/**
 * The ID of the view as specified by the extension.
 */
public static final String ID = "chartvew.views.BarChartView";
private Chart chart;

private static final double[] ySeries = { 0.2, 1.1, 1.9, 2.3, 1.8, 1.5, 1.8, 2.6, 2.9, 3.2 };

@Override
public void createPartControl(Composite parent) {
    // create a chart
    chart = new Chart(parent, SWT.NONE);
    // set titles
    chart.getTitle().setText("Bar Chart");
    chart.getAxisSet().getXAxis(0).getTitle().setText("Data Points");
    chart.getAxisSet().getYAxis(0).getTitle().setText("Amplitude");
    // create bar series
    IBarSeries<?> barSeries = (IBarSeries<?>) chart.getSeriesSet().createSeries(SeriesType.BAR, "bar series");
    barSeries.setYSeries(ySeries);
    // adjust the axis range
    chart.getAxisSet().adjustRange();
    parent.addDisposeListener(new DisposeListener() {

        @Override
        public void widgetDisposed(DisposeEvent e) {
            // This method is called before dispose() is called. This will dispose the chart
            // also making chart.dispose() in dispose() method useless.
            return;

        }
    });
}

@Override
public void dispose() {
    // this dispose has no effect as the chart is already disposed.
    chart.dispose();
    // usually when system does gc errors will be reported in error log. This GC
    // call may not guarantee immediate GC so soon it can report error.
    System.gc();
    super.dispose();
}

@Override
public void setFocus() {
    chart.setFocus();

}

}

`

iloveeclipse commented 7 months ago

Note, Eclipse JVM must be started with -Dorg.eclipse.swt.graphics.Resource.reportNonDisposed=true argument (default in SDK) to see SWT resource leaks reported.

See https://bugs.eclipse.org/bugs/show_bug.cgi?id=570094

raghucssit commented 7 months ago

@eselmeister Please check my project to reproduce the issue. If there is any problem with the project or steps please let me know.

eselmeister commented 7 months ago

Yes, I have your issue on the radar.

eselmeister commented 6 months ago

@raghucssit I have created a test case, based on your data, which can be used to create a crash and imitate the Eclipse View part. So far, the "Dispose Listener" is called and the chart is disposed correctly.

You can start the DemoChartDialog as a simple "Java Application"

eselmeister commented 6 months ago

Screenshot from 2023-12-13 15-03-09

raghucssit commented 5 months ago

@eselmeister Yes i have tried with sample RCP. It works as you said. But when we use it with views Chart#dispose() is called after chart's parent widget is disposed.