PrintDialog/PrintData Bug in 2.5.4.1 ???

If use the PrintDialog like this:

import wx
app= wx.PySimpleApp()
dlg = wx.PrintDialog(None)
dlg.ShowModal()

the dialog runs, but if I use like this:

import wx
app= wx.PySimpleApp()
data = wx.PrintDialogData()
dlg = wx.PrintDialog(None, data)
dlg.ShowModal()

it gives me a segmentation fault.

I dive into the wxWidgets source and found (I think) that the problem is
in the wxPrintData copy constructor src/common/cmndata.cpp line 198:

   (*this) = printData;

I change that line to:

   memcpy( this, &printData, sizeof(printData) );

With that change both python code above runs ok.

Please note that I dont know very much c++ nor the wxWidgets guts, so the
change I've made may not be the best nor the correct, but I think that
something is wrong with the original code.

I'm using:
wx-2.5.4-gtk2-unicode
python 2.3
Fedora Core 3 fully updated

Ricardo

Ricardo Pedroso wrote:

If use the PrintDialog like this:

import wx
app= wx.PySimpleApp()
dlg = wx.PrintDialog(None)
dlg.ShowModal()

the dialog runs, but if I use like this:

import wx
app= wx.PySimpleApp()
data = wx.PrintDialogData()
dlg = wx.PrintDialog(None, data)
dlg.ShowModal()

it gives me a segmentation fault.

It works fine here... Can you tell when the segfault happens? Is it when the wx.PrintDialog is created? During ShowModal? Or is it after ShowModal returns and the isntance is deleted?

I dive into the wxWidgets source and found (I think) that the problem is
in the wxPrintData copy constructor src/common/cmndata.cpp line 198:

   (*this) = printData;

I change that line to:

   memcpy( this, &printData, sizeof(printData) );

With that change both python code above runs ok.

The problem with that change is that you are no longer using the custom assignment operator, but are instead just copying bytes. In many cases that may be fine, but it is not guaranteed to be so, and is not good C++.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Ricardo Pedroso wrote:

If use the PrintDialog like this:

import wx
app= wx.PySimpleApp()
dlg = wx.PrintDialog(None)
dlg.ShowModal()

the dialog runs, but if I use like this:

import wx
app= wx.PySimpleApp()
data = wx.PrintDialogData()
dlg = wx.PrintDialog(None, data)
dlg.ShowModal()

it gives me a segmentation fault.

It works fine here... Can you tell when the segfault happens? Is it
when the wx.PrintDialog is created? During ShowModal? Or is it after
ShowModal returns and the isntance is deleted?

It's when the wx.PrintDialog is created:
dlg = wx.PrintDialog(None, data)

In the src/common/cmndata.cpp I just put two printf's statements, one before
the line:
    (*this) = printData;
and the other after. And just the first one is printed, before the
segfault happen.

I dive into the wxWidgets source and found (I think) that the problem is
in the wxPrintData copy constructor src/common/cmndata.cpp line 198:

   (*this) = printData;

I change that line to:

   memcpy( this, &printData, sizeof(printData) );

With that change both python code above runs ok.

The problem with that change is that you are no longer using the custom
assignment operator, but are instead just copying bytes. In many cases
that may be fine, but it is not guaranteed to be so, and is not good C++.

I didn't realize that the assignment operator was defined I will debug it.

Ricardo.

I didn't realize that the assignment operator was defined I will debug it.

This is what I've done in the assigment operator(just put some printf's):

void wxPrintData::operator=(const wxPrintData& data)
{
    printf("Aqui 1\n");
    m_printNoCopies = data.m_printNoCopies;
    m_printCollate = data.m_printCollate;
    m_printOrientation = data.m_printOrientation;
    m_printerName = data.m_printerName;
    m_colour = data.m_colour;
    m_duplexMode = data.m_duplexMode;
    m_printQuality = data.m_printQuality;
    m_paperId = data.m_paperId;
    m_paperSize = data.m_paperSize;
    m_bin = data.m_bin;
    m_printMode = data.m_printMode;
    m_filename = data.m_filename;

    printf("Aqui 2\n");
    // UnRef old m_nativeData
    if (m_nativeData)
    {
        m_nativeData->m_ref--;
        if (m_nativeData->m_ref == 0)
            delete m_nativeData;
    }
    // Set Ref new one
    printf("Aqui 3\n");
    m_nativeData = data.GetNativeData();
    m_nativeData->m_ref++;

    if (m_privData)
    {
        printf("Aqui 3.1\n");
        delete m_privData;
        printf("Aqui 3.2\n");
        m_privData = NULL;
    }
    printf("Aqui 4\n");
    m_privDataLen = data.GetPrivDataLen();
    if (m_privDataLen > 0)
    {
        m_privData = new char[m_privDataLen];
        memcpy( m_privData, data.GetPrivData(), m_privDataLen );
    }
    printf("Aqui 5\n");

#ifdef __WXMAC__
    m_nativePrintData->CopyFrom( data.m_nativePrintData ) ;
#endif
}

···

-----------------------------------------------------
This is the python program that I use to debug:

import wx
app= wx.PySimpleApp()
print 'Creating data'
data = wx.PrintDialogData()
print 'Creating dialog'
dlg = wx.PrintDialog(None, data)
dlg.ShowModal()

--------------------------------------------------------
This is the python test program output:

[rpedroso@portatil ~]$ python p.py
Creating data
Creating dialog
Aqui 1
Aqui 2
Aqui 3
Aqui 4
Aqui 5
Aqui 1
Aqui 2
Aqui 3
Aqui 3.1
Segmentation fault

In conclusion, the segfault is when we are freeing the m_privData:

        delete m_privData;

----------------------------------------------------------
In one of my debugs, instead of a segmentation fault, I had this:
*** glibc detected *** double free or corruption (!prev): 0x00ad8110 ***
Aborted

I don't know if it will help but,
I google for it and one thing I found was someone tell that:
(double free error)
"
Using Fedora Core 3 (latest release, fully upgraded), I encountered an
error. This release of Fedora uses a new glibc which does not allow one to
perform a free() on the same location twice. (Since glibc-20040925T0738,
released in glibc 2.3.4)
"

I hope, this big mail, help.

Ricardo

I did more research on this print issue and I end up changing the
src/gtk/gnome/gprint.cpp ( I didnt say before but I'm using the gnome
print suport), those are the changes:

413d412
< wxPrintData data = m_printDialogData.GetPrintData();
416c415
< (wxGnomePrintNativeData*) data.GetNativeData();

···

---

      (wxGnomePrintNativeData*)

m_printDialogData.GetPrintData().GetNativeData();
670d668
< wxPrintData printdata = GetPrintDialogData().GetPrintData();
672c670
< (wxGnomePrintNativeData*) printdata.GetNativeData();
---

        (wxGnomePrintNativeData*)

GetPrintDialogData().GetPrintData().GetNativeData();

With this changes, the HtmlWindow.py and the PrintDialog.py from demos,
work again. The PrintFramework.py stills give me segfaults but the problem
with this could be other.

Just for curiosity see this:
https://bugzilla.redhat.com/beta/show_bug.cgi?id=144142

Ricardo

Ricardo Pedroso wrote:

I did more research on this print issue and I end up changing the
src/gtk/gnome/gprint.cpp ( I didnt say before but I'm using the gnome
print suport), those are the changes:

All this does is avoid using the copy operator, so if the problem is really there then this isn't really fixing it...

I've bounced this over to wx-dev, maybe somebody there can see the problem.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Ricardo Pedroso wrote:

I did more research on this print issue and I end up changing the
src/gtk/gnome/gprint.cpp ( I didnt say before but I'm using the gnome
print suport),

Could you please try it with this change instead?

Index: src/common/cmndata.cpp

···

===================================================================
RCS file: /pack/cvsroots/wxwidgets/wxWidgets/src/common/cmndata.cpp,v
retrieving revision 1.112
diff -u -4 -r1.112 cmndata.cpp
--- src/common/cmndata.cpp 2005/02/28 01:51:57 1.112
+++ src/common/cmndata.cpp 2005/03/21 19:44:07
@@ -194,8 +194,9 @@
  wxPrintData::wxPrintData(const wxPrintData& printData)
      : wxObject()
  {
      m_nativeData = NULL;
+ m_privData = NULL;
      (*this) = printData;
  }

  void wxPrintData::SetPrivData( char *privData, int len )

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Could you please try it with this change instead?

Index: src/common/cmndata.cpp

RCS file: /pack/cvsroots/wxwidgets/wxWidgets/src/common/cmndata.cpp,v
retrieving revision 1.112
diff -u -4 -r1.112 cmndata.cpp
--- src/common/cmndata.cpp 2005/02/28 01:51:57 1.112
+++ src/common/cmndata.cpp 2005/03/21 19:44:07
@@ -194,8 +194,9 @@
  wxPrintData::wxPrintData(const wxPrintData& printData)
      : wxObject()
  {
      m_nativeData = NULL;
+ m_privData = NULL;
      (*this) = printData;
  }

  void wxPrintData::SetPrivData( char *privData, int len )

I've undo my changes to the gprint.cpp then aplly this patch.

I tried, from demos, the HtmlWindow.py, PrintFramework.py and the
PrintDialog.py and it's working. Thanks.

There is, still, a small issue in the PrintFramework.py.
When I run it and try to print, this is the output:

[rpedroso@portatil demo]$ python PrintFramework.py
wx.VERSION_STRING = 2.5.4.1
pid: 4058
01:04:18 PM: wx.Printout.OnPreparePrinting
01:04:18 PM: wx.Printout.GetPageInfo
01:04:18 PM: wx.Printout.OnBeginPrinting
01:04:18 PM: wx.Printout.OnBeginDocument
01:04:18 PM: wx.Printout.HasPage: 1
01:04:18 PM: wx.Printout.OnPrintPage: 1
Traceback (most recent call last):
  File
"/home/rpedroso/wx/wxPython-src-2.5.4.1/wxPython/demo/PrintFramework.py",
line 67, in OnPrintPage
    (w, h) = dc.GetSizeTuple()
AttributeError: 'Object' object has no attribute 'GetSizeTuple'
01:04:18 PM: wx.Printout.HasPage: 2
01:04:18 PM: wx.Printout.OnPrintPage: 2
Traceback (most recent call last):
  File
"/home/rpedroso/wx/wxPython-src-2.5.4.1/wxPython/demo/PrintFramework.py",
line 67, in OnPrintPage
    (w, h) = dc.GetSizeTuple()
AttributeError: 'Object' object has no attribute 'GetSizeTuple'
01:04:18 PM: wx.Printout.OnEndDocument
01:04:18 PM: wx.Printout.OnEndPrinting

But not of the demos give me a segfault anymore.

Ricardo

Ricardo Pedroso wrote:

There is, still, a small issue in the PrintFramework.py.
When I run it and try to print, this is the output:

[rpedroso@portatil demo]$ python PrintFramework.py
wx.VERSION_STRING = 2.5.4.1
pid: 4058
01:04:18 PM: wx.Printout.OnPreparePrinting
01:04:18 PM: wx.Printout.GetPageInfo
01:04:18 PM: wx.Printout.OnBeginPrinting
01:04:18 PM: wx.Printout.OnBeginDocument
01:04:18 PM: wx.Printout.HasPage: 1
01:04:18 PM: wx.Printout.OnPrintPage: 1
Traceback (most recent call last):
  File
"/home/rpedroso/wx/wxPython-src-2.5.4.1/wxPython/demo/PrintFramework.py",
line 67, in OnPrintPage
    (w, h) = dc.GetSizeTuple()
AttributeError: 'Object' object has no attribute 'GetSizeTuple'
01:04:18 PM: wx.Printout.HasPage: 2
01:04:18 PM: wx.Printout.OnPrintPage: 2
Traceback (most recent call last):
  File
"/home/rpedroso/wx/wxPython-src-2.5.4.1/wxPython/demo/PrintFramework.py",
line 67, in OnPrintPage
    (w, h) = dc.GetSizeTuple()
AttributeError: 'Object' object has no attribute 'GetSizeTuple'

I've found the problem. The wxRTTI info for wxGnomePrintDC bypassed the wxDC base class and so the code in wxPython that searches for what type to use for return values was only able to safely choose wx.Object. It will be fixed in the next preview release.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

I am also getting a crash in the same place (operator=)
with 2.5.4.1 but it turns up with 2.5.2.8 as well. To
reproduce with BitPim, start it up, File > Print > Page
Setup > Ok > Print Preview. It occurs with Windows,
Linux and Mac.

Here is the trace from Mac.

Exception: EXC_BAD_ACCESS (0x0001)
Codes: KERN_INVALID_ADDRESS (0x0001) at 0xfffffff4

Thread 0 Crashed:
0 libwx_macud-2.5.4.dylib 0x0305fb80 wxStringBase::operator=(wxStringBase const&) + 0x28
1 libwx_macud-2.5.4.dylib 0x03126d80 wxPrintData::operator=(wxPrintData const&) + 0x3c
2 libwx_macud-2.5.4.dylib 0x0316d07c _ZN18wxPrintPreviewBaseC4EP10wxPrintoutS1_P11wxPrintData + 0x60
3 libwx_macud-2.5.4.dylib 0x0316e474 _ZN14wxPrintPreviewC4EP10wxPrintoutS1_P11wxPrintData + 0x2c
4 _windows_.so 0x00a73df8 init_windows_ + 0x4800
5 _windows_.so 0x00a6941c wxPyPreviewControlBar::base_SetZoomControl(int) + 0x57f04
6 org.python.Python.framework 0x95f4a8d0 PyObject_Call + 0x30
...

Roger