Forum Bugs

prince.exe processes getting stuck and consuming cpu

Bill.French
(dummy first post so I can post url information)
Bill.French
Hello. We call Prince through an asp.net application. It seems to be fine, but I have noticed the cpu pegged on the server occasionally, with several prince.exe services running and consuming the cpu. I rebooted the server yesterday, and noticed the cpu pegged again.

Any suggestions for how to troubleshoot this? I am not able to recreate it myself. The source code and a sample link are below.

Thanks!!

Sample link:
http://pdf.ptsem.edu/digital/default.aspx?src=BR1844163.xml&div=5&print=all

using System;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Net;
using System.IO;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string src = Request.QueryString["src"];
        string div = Request.QueryString["div"];
			
		if (!string.IsNullOrEmpty(src) && !string.IsNullOrEmpty(div)) {
			
			WebRequest request = WebRequest.Create("http://digital.library.ptsem.edu/default.xqy?src=" + src + "&div=" + div + "&print=all");
			WebResponse response = request.GetResponse();

			Stream responseStream = response.GetResponseStream();
			StreamReader outputStream = new StreamReader(responseStream);

			string Output = outputStream.ReadToEnd();

			Prince princeConverter = new Prince(@"C:\Program Files\Prince\Engine\bin\prince.exe");
			princeConverter.AddStyleSheet(@"C:\Program Files\Prince\CSS\print.css");

			Response.AddHeader("Content-Type", "application/pdf");
			princeConverter.ConvertString(Output, Response.OutputStream);
			
		}
    }
}
mikeday
Your code looks fine to me. How many requests do you think the code is handling per day? You could try enabling a log file with SetLog(), to try and see if it is hanging on the same pages all the time or not.
jeric
We had the same problem with php on linux.
We discovered that the problem only occured if a user hit escape (or the stop button in his browser). Then the current request was terminated and the prince process eats 100% cpu without finishing.

The cause of this problem was found after reading this comment:
http://nl3.php.net/manual/en/function.proc-open.php#54047

Singnal handling is inherited from the webserver/fcgi-server, this means that the handling of SIGPIPE is disabled causing princexml not to receive the SIGPIPE signal.

We solved this by adding a ignore_user_abort() function call in php (http://nl3.php.net/ignore_user_abort)
Not sure if there is an equivalent in asp.net
mikeday
Thanks jeric, that's very informative. Perhaps Prince should reset SIGPIPE itself to help avoid this situation.

Bill, are you able to reproduce the problem by accessing the ASP page several times in the browser and pressing stop before you receive the generated PDF?
Bill.French
Well, we haven't had the issue again since I made the original posting. I tried several times to hit escape in the browser at various points in the process, but no luck recreating the issue. Thanks for the help, I have been keeping an eye on the server and will write back with any updates.
joomlaman
Hello-

The reason this is happening is that you are not specifying a content-length in your headers. While this is perfectly fine in FireFox, this will cause IE to close the file or give an error about it not being found at all. In my case, Internet Explorer will actually open the file and start to render the PDF, but then it immediately closes it, causing Prince to consume 100% CPU time.

All of the fixes are posted in this thread except the code is for PHP.
http://www.princexml.com/bb/viewtopic.php?t=1006

The best solution at the moment according to my research is to buffer the file to a temporary file on the server, then get the filesize, then output the file to the client along with the proper Content-length header.
mikeday
Relating to the earlier comment, we have made a change in Prince 6.0 rev 6 to reset the SIGPIPE signal handler, hopefully reducing the chance of this deadlock problem when running Prince under PHP.
Worker
I just noticed this problem running Prince 6.0 rev 6 via Perl and Apache on Windows XP and accessing it using IE7. When the "save/open/cancel" dialog opens in IE, if I choose "cancel" the prince.exe process starts spinning near 100%.

This only happens in IE (not Firefox), and only happens when Prince outputs directly to STDOUT.

Small changes in the HTML (such as replacing one letter with another letter) make the problem disappear. However, I now have a testcase that, for my set-up, will cause it to happen every time.

Based on what joomlaman said, I just tried the following:
  • Output the pdf to a file and note the filesize.
  • Include a content-length header of the correct size in the Perl script.
  • Output the pdf to STDOUT again.
This did not make the problem go away.

Edit: With the content-length header the problem persists if "cancel" is pressed quickly after the prompt opens. If you wait a while, the problem may be gone. I'm also no longer sure about "happens every time". :)
Worker
Is there anything I can do to help nail down this problem? Outputing the pdf to a file and then streaming it works, but I don't think that's the optimal set-up.
mikeday
You can easily reproduce the problem, calling Prince from a Perl CGI script called from Apache on Windows XP, right? Since it's Windows, the process won't be killed by SIGPIPE even if the stdout pipe is closed unexpectedly. So it is up to Prince to detect a write error and stop trying to write. Just out of curiosity, do you get any log output from Prince when this problem occurs? For example, does it show Prince beginning to format the document, but failing to finish?
mikeday
After looking at the problem we've created a new test build of Prince,
prince-6.0r7-beta2-setup.exe, which may solve the zombie problem that occurs when writing a PDF file to standard output when standard output is unexpectedly closed by the web server. Please let me know if it solves the problem! :)
Worker
With r6, I did not get any log output (using --log) from Prince when then problem occurs. Just a 0-byte log file.

This new build appears to solve the problem. Now my log files contain the following:
Tue Jun 17 10:00:58 2008: ---- begin
Tue Jun 17 10:01:03 2008: internal error: error_writing_to_buffer
Tue Jun 17 10:01:03 2008: ---- end

If I see the problem appear again, I'll definitely let you know. But right now, all of my tests that were hanging before are exiting nicely (with that error in the log). Thanks!
mikeday
Today we have released Prince 6.0 rev 7, which includes the fix for this problem.