Bug 67579

Summary: assertion failure on "print option": too much trust in printer settings/data saved in the .odt file
Product: LibreOffice Reporter: Lionel Elie Mamane <lionel>
Component: Printing and PDF exportAssignee: Not Assigned <libreoffice-bugs>
Status: NEW --- QA Contact:
Severity: normal    
Priority: medium CC: caolanm, lo_bugs
Version: 4.2.0.0.alpha0+ Master   
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
See Also: https://bugs.freedesktop.org/show_bug.cgi?id=58080
Whiteboard:
i915 platform: i915 features:
Attachments: gdb backtrace

Description Lionel Elie Mamane 2013-07-31 12:52:21 UTC
Created attachment 83360 [details]
gdb backtrace

@caolan: this is your assert. An opinion? Something I should try?

1) Using a *dbgutil* build of master
2) Open writer document
3) Open print dialog
4) click on "options"

Result: assertion failure

Console:

 soffice.bin: /home/master/src/libreoffice/workdirs/libreoffice-4.2/padmin/source/prtsetup.cxx:364: padmin::RTSDevicePage::RTSDevicePage(padmin::RTSDialog*): Assertion `nLevelEntryData != 0 || bAutoIsPDF == m_pParent->m_aJobData.m_nPDFDevice' failed.

Backtrace attached. The interesting frame is frame 9 or 55? The stack is a bit weird; the abort signal handler seems to indirectly call the same code again...


Here's the code around that:


    sal_uLong nLevelEntryData = 0; //automatic
    if( m_pParent->m_aJobData.m_nPDFDevice == 2 ) //explicitly PDF
        nLevelEntryData = 10;
    else if (m_pParent->m_aJobData.m_nPSLevel > 0) //explicit PS Level
        nLevelEntryData = m_pParent->m_aJobData.m_nPSLevel+1;
    else if (m_pParent->m_aJobData.m_nPDFDevice == 1) //automatically PDF
        nLevelEntryData = 0;
    else if (m_pParent->m_aJobData.m_nPDFDevice == -1) //explicitly PS from driver
        nLevelEntryData = 1;

    bool bAutoIsPDF = officecfg::Office::Common::Print::Option::Printer::PDFAsStandardPrintJobFormat::get();

    assert(nLevelEntryData != 0 || bAutoIsPDF == m_pParent->m_aJobData.m_nPDFDevice);


and:

(gdb) print nLevelEntryData
$1 = 0
(gdb) print bAutoIsPDF
$2 = true
(gdb) print m_pParent->m_aJobData.m_nPDFDevice
$3 = 0
(gdb) print m_pParent->m_aJobData.m_nPSLevel
$4 = 0
Comment 1 Lionel Elie Mamane 2013-07-31 16:08:55 UTC
So, using gdb I skipped that assert *once* and then ran again in gdb.

Now that assert succeeds because m_Parent->m_aJobData.m_nPDFDevice==1.

However, when I dismiss the properties page (click "OK"), I ultimately get into this code:

padmin::RTSDialog::ClickButton



        if( m_pDevicePage )
        {
            m_aJobData.m_nColorDepth    = m_pDevicePage->getDepth();
            m_aJobData.m_nColorDevice   = m_pDevicePage->getColorDevice();
            m_aJobData.m_nPSLevel       = m_pDevicePage->getLevel();
            m_aJobData.m_nPDFDevice     = m_pDevicePage->getPDFDevice();
        }


This sets m_aJobData.m_nPDFDevice to 0, but well after the assert. So in a nutshell, I cannot reproduce anymore.


Let's look at the .odt file... settings.xml contains:


<office:document-settings>
  <office:settings>
        <config:config-item-set config:name="ooo:configuration-settings">
            <config:config-item config:name="PrinterSetup" config:type="base64Binary">

And (decoded), this contains:

 pslevel=0
 pdfdevice=0

Aha. So let's try to restart the LibreOffice process on the same file...


More analysis / notes:

m_pParent->m_aJobData seems to be essentially constructed in PspSalInfoPrinter::Setup (file vcl/generic/print/genprnpsp.cxx).

In this case, since pJobSetup->mpDriverData is not NULL, we go into SetData( ~0, pJobSetup ), which calls JobData::constructFromStreamBuffer.

JobData::constructFromStreamBuffer *does* set m_nPDFDevice to 1.

SetData then goes on to create a new StreamBuffer from the information, and returns to PspSalInfoPrinter::Setup, which calls ... JobData::constructFromStreamBuffer again on the StreamBuffer with same contents as the one that SetData worked on, which thus *also* sets m_nPDFDevice to 1.

So we enter Sal_SetupPrinterDriver (file padmin/source/prtsetup.cxx) with a rJobData that has m_nPDFDevice==1, which creates a padmin::RTSDialog passing it the same rJobData; that class copies it into its m_aJobData.
Comment 2 Lionel Elie Mamane 2013-07-31 16:14:37 UTC
Yup, if I restart LibreOffice, I get the assertion failure again. So it seems that LibreOffice trusts settings.xml "too much".
Comment 3 Lionel Elie Mamane 2013-07-31 16:28:45 UTC
In a run where the assert happens:

In PspSalInfoPrinter::Setup, before the call to SetData:

gdb) print (char*)pJobSetup->mpDriverData
$95 = 
    0x299e9b0 "JobData 1\nprinter=C353\norientation=Portrait\ncopies=1\nmargindajustment=0,0,0,0\ncolordepth=24\npslevel=0\npdfdevice=0\ncolordevice=0\nPPDContexData\nInputSlot:Tray1"


So, the pdfdevice=0 from settings.xml somehow gets there. Not sure why / how; that setting seems like it is printer-dependent to me. Why would it be trusted from an .odt (and why it is saved there in the first place), I'm not completely sure, since the printer environment may have changed since the file was saved. It may even be a different printer.

From there, it trickles down to RTSDialog's m_aJobData and triggers the assert.
Comment 4 Lionel Elie Mamane 2013-07-31 16:54:19 UTC
When creating a new file, I cannot reproduce the "pdfdevice=0" setting being included. It must have been inherited from a save with an older version of LibreOffice.

Manually emptying PrinterSetup in settings.xml fixes the crash.

The assert-failure-inducing "pdfdevice=0" survives:

 - file / save as
 - 'print directly' from toolbar then file / save
 - 'print' (dialog) / OK, then file / save

It does not survive:

 - print (dialog), select other printer, select default printer again,
   OK (it prints), then file / save
Comment 5 Lionel Elie Mamane 2013-07-31 17:08:37 UTC
Hmmm... This seems extremely related to the situation / scenario described in bug 58080. My guess:

In bug 58080, the "Generic Printer" business pollutes the "pdfdevice" setting (in memory) and puts 0 there. Then I save the file (in bug 58080, the assert fails only the second time the print dialog is opened).

After printing the file *once* in the "Generic Printer" situation, I saved the file, which saved the bad "pdfdevice=0" in the file, leading to this bug.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.