Link to home
Start Free TrialLog in
Avatar of Sevron
Sevron

asked on

Classic ASP Script Timed Out

Hi,

We are experiencing a number of issues with one of our classic ASP pages in our software.
It is an intermittent issue where the page times out, it takes over 60 seconds to load.
The page in question generates a PDF document using a third party software called ABCPDF.

We are a little confused as to what the issue is as it doesn't happen all the time it seems to come and go.

I have attached the failed request log file as im not too familiar with them and was hoping someone could point me in the right direction as to why the timeout may be happening.

fr000001.xml

dim theURL,theID,theCount,i,theDoc

Set theDoc = Server.CreateObject("ABCpdf9.Doc")

theDoc.HtmlOptions.Timeout = 60000

theDoc.MediaBox = "0 0 595 845"

'We add the first page and indicate that we will be adding more pages by telling the Doc object that this is page one. We save the returned ID as this will be used to add subsequent pages.
If request("version")="2" then
	if request("interserve")="1" then
		theURL = "simple_prototype_report_2.asp"
	else
		theURL = "simple_prototype_report_1.asp"
	end if
else
	theURL = "simple_report_1.asp"
end if

If request("version")="2" then
	theDoc.Rect = "0 60 595 820"
else
	theDoc.Rect = "0 80 595 820"
end if
theDoc.HtmlOptions.AddLinks = True
theID = theDoc.AddImageUrl(theURL)

Open in new window


Thanks.
Avatar of Gary
Gary
Flag of Ireland image

Why not just increase your timeout on that page - hard to debug something that could be server specific or related to other things happening on the server at the time.
is this all of your code? hard to tell what the issue is with what you've given. the error log in way too big to comb through, even doing a search for the word "error" didn't yield anything.

you could try using the Recount Property to have the app keep trying if it fails:

theDoc.HtmlOptions.RetryCount = 10;

you could also try increasing the Page timeout property by using Server.ScriptTimeOut:

'-- put at the top of your page
Server.ScriptTimeOut = 120      '-- 120 second timeout limit
Avatar of Sevron
Sevron

ASKER

Hi thanks for the quick replies.
No that wasent all the code I will post the complete code below.
As for increasing the timeout it doesn't seem to have any effect it just runs and runs even at 2 minutes.
I didn't write the code its a legacy system built by someone years ago and im trying to figure out whats wrong to no avail atm.

<%@ LANGUAGE = VBScript %>
<% option explicit %>
<% response.Expires=-1 %>
<!--#include file="secure/Connections/security_check.asp" -->
<!--#include file="secure/Connections/connect_1.0.4.asp" -->
<!--#include file="includes/email_sender_1.0.0_important.asp" -->

<%		

Function RemoveShit(userInput)
	Dim newString, regEx
	Set regEx = New RegExp
	regEx.Pattern = "([^A-Za-z0-9_{}-]+)"
	regEx.IgnoreCase = True
	regEx.Global = True
	newString = regEx.Replace(userInput, "")
	Set regEx = nothing
	RemoveShit = newString
End Function

	dim new_file_name, email_file_name
	dim Approval : Approval = ""
	dim email_status
	
	Call open_conn()

	dim cid, fid, question

	if request.form("pkCOSHH_AssessmentID")="" or Isnull(request.form("pkCOSHH_AssessmentID"))=true then
		cid=request("cid")
		fid=Server.HTMLEncode(request("fid"))
		question=request("q")
	Else
		cid=request.form("pkCOSHH_AssessmentID")
		fid=request.form("fileid")
		question=request.form("question")
	end if
	
	if request("num")="" or request("num")="1" or request("num")="2" then
	
	  ' *** update record in DB			
	  sql = "dbo.SP_v2_coshh_report_simple_generate_rev002 ?,?,?,?,?,?"
	  Call open_command_read(sql)
	  'Add Parameter.
	  'INT=3  /  Varchar = 200  /  Boolean = 11  /  Currency = 6  /  yyyymmdd = 133  /  Float = 4
	  Call AddParameter("@pkContactID",3,1,15,Session("pkContactID"))
	  Call AddParameter("@pkCOSHH_AssessmentID",3,1,15,cid)
	  Call AddParameter("@pkCOSHH_FormID",3,1,15,question)
	  Call AddParameter("@num",200,1,15,request("num"))
	  Call AddParameter("@without_sos",200,1,15,request("sos"))
	  Call AddParameter("@isds",200,1,15,request("isds"))
	  'Execute Query.
	  Set rc = rc.execute()			

	  ' *** store in array				
	  if not rc.EOF then
		  
		 new_file_name = rc("new_file_name")
		  
	  end if
	  	  
	end if
	
	if request("num")="2" then
		new_file_name = rc("new_file_name")
		email_file_name = cid & "_" & inputfilter(fid)
	end if
	
	if request("num")="3" then
		new_file_name = "Draft_" & cid & "_" & inputfilter(fid)
	end if
	
	if request("num")="4" then
		new_file_name = "Draft_" & cid & "_" & inputfilter(fid)
	end if
		
	  Call close_conn()
	  
	if request("num")="" or request("num")="1" or request("num")="2" then	    
	  
		' *** SEND RISK MONITORING ALERTS.
		sql = "[SP_v2_risk_monitoring_alert_email_list] ?,?,?"
		Call open_conn()
		Call open_command_read(sql)

		Call AddParameter("@pkCOSHH_AssessmentID",3,1,15,cid)
		Call AddParameter("@pkCompanyID",3,1,15,session("pkCompanyID"))
		Call AddParameter("@pkSDSID",3,1,15,0)
		'Execute Query.
		Set rc = rc.execute()
		If not rc.eof then
			getRecord = rc.getRows()
		end if
		call close_conn()
		
		if isarray(getRecord)=true then
		for counter=0 to ubound(getRecord,2)
		
		  Set ObjEmail_Sender = new Email_Sender
		  email_from = ("support@system.co.uk")
		  email_subject = "Monitoring Alert"
		  email_attachment = null
		  'Send Email
		  email_to = getRecord(2,counter)
		  email_bcc = null
		  email_status = true
		  email_body = "risk_monitoring_alert.asp?"
		  email_body = email_body & "r=" & getRecord(0,counter)
		  email_body = email_body & "&c=" & getRecord(3,counter)
		  email_body = email_body & "&s=0"
		  Call ObjEmail_Sender.Send_Email(email_from,email_to,email_bcc,email_subject,email_body,email_attachment,email_status)
		  set ObjEmail_Sender=nothing
		  
		  if counter = 0 then
		  	if isnull(getRecord(4,counter))=false then
		 		Approval = getRecord(2,counter)
			end if
		  end if

		next	  
		end if
		
		getRecord=""
	  
	 END IF
	  
%>

<%												
	
%>
<%

dim theURL,theID,theCount,i,theDoc

Set theDoc = Server.CreateObject("ABCpdf9.Doc")

theDoc.HtmlOptions.Timeout = 60000

theDoc.MediaBox = "0 0 595 845"

'We add the first page and indicate that we will be adding more pages by telling the Doc object that this is page one. We save the returned ID as this will be used to add subsequent pages.
If request("version")="2" then
	if request("interserve")="1" then
		theURL = "simple_prototype_report_2.asp?pkCompanyID=" & session("pkCompanyID") & "&pkContactID=" & session("pkContactID") & "&id=" & inputfilter(cid) & "&username=" & inputfilter(session("username")) & "&num=" & inputfilter(request("num"))
	else
		theURL = "simple_prototype_report_1.asp?&pkCompanyID=" & session("pkCompanyID") & "&pkContactID=" & session("pkContactID") & "&id=" & inputfilter(cid) & "&username=" & inputfilter(session("username")) & "&num=" & inputfilter(request("num"))
	end if
else
	theURL = "simple_report_1.asp?pkContactID=" & session("pkContactID") & "&id=" & inputfilter(cid) & "&username=" & inputfilter(session("username"))
end if

If request("version")="2" then
	theDoc.Rect = "0 60 595 820"
else
	theDoc.Rect = "0 80 595 820"
end if
theDoc.HtmlOptions.AddLinks = True
theID = theDoc.AddImageUrl(theURL)


'We now chain subsequent pages together. We stop when we reach a page which wasn't truncated.

Do
  'theDoc.FrameRect
  If Not theDoc.Chainable(theID) Then Exit Do
  theDoc.Page = theDoc.AddPage()
  theID = theDoc.AddImageToChain(theID)
Loop

if request("interserve")="1" then
    if request("sos")<>"1" then
		theDoc.Page = theDoc.AddPage()
		theURL = "action_assessment_preview_soap.asp"
		'theDoc.HtmlOptions.ImageQuality = 101
		theDoc.AddImageUrl(theURL)
	end if
end if

theCount = theDoc.PageCount

theDoc.Rect = "0 45 595 60"
theDoc.HPos = 0.5
theDoc.VPos = 0.5
theDoc.Color = "0 0 0"

dim theF1
theF1 = theDoc.AddFont("Verdana")
theDoc.FontSize = 8
theDoc.Font = theF1 


If request("version")="2" then

	theDoc.Rect = "0 30 595 55"
	theDoc.HPos = 0.5
	theDoc.VPos = 0.5
	theDoc.Color = "0 0 0"
		
	For i = 1 To theCount
	  theDoc.PageNumber = i
	  theDoc.AddHtml "<p>Page " & i & " of " & theCount & " (Ref: " & inputfilter(fid) & ")</p><p>Produced using Software (v2.2) &copy;</p>"
	Next
else
	For i = 1 To theCount
	  theDoc.PageNumber = i
	  theDoc.AddText "Page " & i & " of " & theCount & " (Ref: " & inputfilter(fid) & ")"
	Next
	
	theDoc.Rect = "0 35 595 45"
	theDoc.HPos = 0.5
	theDoc.VPos = 0.5
	theDoc.Color = "0 0 0"
	
	For i = 1 To theCount
	  theDoc.PageNumber = i
	  theDoc.AddText "Produced using Software (v2.2)"
	Next
end if

'After adding the pages we can flatten them. We can't do this until after the pages have been added because flattening will invalidate our previous ID and break the chain.
dim theAngle
if request("num")="3" OR request("num")="4" then
  theDoc.FontSize = 48
  theDoc.Rect = "0 60 700 900"
  theAngle = 55
  theDoc.Color = "133 0 0"
  theDoc.Color.Alpha = 255 / 2
  theDoc.Transform.Rotate theAngle, 380, 400
end if

if len(Approval)>0 then
  theDoc.FontSize = 55
  theDoc.Rect = "0 60 700 900"
  theAngle = 55
  theDoc.Color = "133 0 0"
  theDoc.Color.Alpha = 255 / 2
  theDoc.Transform.Rotate theAngle, 380, 400
end if

For i = 1 To theCount
  theDoc.PageNumber = i
	if request("num")="3" OR request("num")="4" then
		theDoc.AddText "DRAFT ONLY - NOT FOR USE"
	end if
	if len(Approval)>0 then
	  theDoc.FontSize = 55
	  theDoc.Rect = "0 60 700 900"
	  theDoc.AddText "APPROVAL REQUIRED"
	  theDoc.FontSize = 35
	  theDoc.Rect = "0 50 600 800"
	  theDoc.AddText "Email sent to " & Approval
	end if
  theDoc.Flatten
Next

'*** Append SDS if required
dim theDoc2
if request("isds")="1" then
	' *** securely select record using parameterised query.	
	sql = "SP_v2_coshh_report_publish_substances_only ?"
	Call open_conn()
	Call open_command_read(sql)
	'Add Parameter.
	'INT=3  /  Varchar = 200  /  Boolean = 11  /  Currency = 6  /  yyyymmdd = 133  /  Float = 4
	Call AddParameter("@pkCOSHH_AssessmentID",3,1,15,cid)
	'Execute Query.
	Set rc = rc.execute()
	dim getSubstance
	If not rc.eof then
		getSubstance = rc.getRows()
		for counter=0 to ubound(getSubstance,2)
			' Declare some variables
			Dim fs
			Dim oldFile, newFile
			Set fs = Server.CreateObject("Scripting.FileSystemObject")
			' Check if file to be renamed exists
			If NOT fs.FileExists("MSDS_Store\" & getSubstance(0,counter) & "") Then
				'**do nothing
			else
				Set theDoc2 = Server.CreateObject("ABCpdf9.Doc")
				theDoc2.Read "MSDS_Store\" & getSubstance(0,counter) & "" 
				theDoc.Append theDoc2
				Set theDoc2 = nothing
			End If
			Set fs = Nothing
		next
	end if
	Call close_conn()
end if

'Finally we save. 
dim newdoc, emaildoc
if request("num")="3" OR request("num")="4" then
emaildoc = "Assessment_Store\" & RemoveShit(new_file_name) & ".PDF"
newdoc = "Assessment_Store\" & RemoveShit(new_file_name)
theDoc.Save "Assessment_Store\" & RemoveShit(new_file_name) & ".PDF"
elseif request("num")="2" then
emaildoc = "Assessment_Store\" & RemoveShit(email_file_name) & ".PDF"
theDoc.Save "Assessment_Store\" & RemoveShit(email_file_name) & ".PDF"
newdoc = "Assessment_Store\" & RemoveShit(new_file_name)
theDoc.Save "Assessment_Store\" & RemoveShit(new_file_name)
else
newdoc = "Assessment_Store\" & RemoveShit(new_file_name)
theDoc.Save "Assessment_Store\" & RemoveShit(new_file_name)
end if

'*** CREATE SALUTATION
dim namesplit, switchit
if instr(InputFilter(Session("Username")),",")>0 then
  namesplit = split(InputFilter(Session("Username")),",")
  switchit = 1
else
  namesplit = split(InputFilter(Session("Username"))," ")
  switchit = 0
end if
dim firstName : firstName = ""
if isarray(namesplit)=true then
  firstName=namesplit(switchit)
end if
If firstName <> "" Then
  firstName = "Hi "&ucase(left(firstName, 1)) + right(firstName, len(firstName)-1)
Else
  firstName = "To whom it may concern"
End If

if request("num")="3" or request("num")="2" then

	  '*** send login email to user
	  Set ObjEmail_Sender = new Email_Sender
	  email_from = "actions@system.co.uk"
	  if request("num")="3" then
		  email_subject = "Draft Risk Assessment ()"
	  else
		  email_subject = "Published Risk Assessment ()"
	  end if
	  email_attachment = emaildoc
	  email_status = null
	  'Send Email
	  email_to = InputFilter(Session("Useremail"))
	  email_bcc = null
	  email_body = "email_assessment.asp?"
	  email_body = email_body & "name=" & server.URLEncode(firstName)
	  email_body = email_body & "&email=" & server.URLEncode(InputFilter(Session("Useremail")))
	  email_body = email_body & "&num=" & request("num")
	  Call ObjEmail_Sender.Send_Email(email_from,email_to,email_bcc,email_subject,email_body,email_attachment,email_status)
	  set ObjEmail_Sender=nothing

end if


	dim binaryDoc
	binaryDoc = theDoc.GetData()
	
		Response.Clear()
		Response.ContentType = "application/pdf"
		if request("num")="3" OR request("num")="4" then
		Response.AddHeader "content-disposition", "attachment; filename="&inputfilter(RemoveShit(fid))&"_(DRAFT).PDF"
		else
		Response.AddHeader "content-disposition", "attachment; filename="&inputfilter(RemoveShit(fid))&".PDF"
		end if

		Response.BinaryWrite(binaryDoc)
		

Set theDoc = nothing

If Err Then
   Response.Write("<B>Failed!</B> " + Err.Description + "<BR>" + RemoveShit(new_file_name) + "<BR>" + session("systemURL"))
   Response.End
End If

%>

Open in new window

are you able to duplicate the error?
Avatar of Sevron

ASKER

Yes, I have logged into a users account and tried to publish the same page they were attempting and it just timed out.
However I have noticed if the server gets restarted the problem goes away for a while.
Could this be due to something on the server eating up all the resources?
it def COULD be, hard to tell without narrowing things down a bit.

since you're able to reproduce the time out issue, I would first see if it's related to the database or the creation of the doc. I noticed you have several calls to the database using stored procedures. Try putting in a Response.End right around the end of the database calls. I would put in in the code segment below:

Response.end

dim theURL,theID,theCount,i,theDoc

Set theDoc = Server.CreateObject("ABCpdf9.Doc")

theDoc.HtmlOptions.Timeout = 60000

Open in new window


this should tell us if it's database related or not.
I'm assuming each user has their own version of the report (based on the code)?
If so it could be something specific to that user in the sql/stored procedure params that you are passing that is timing out and not the actual asp page
Avatar of Sevron

ASKER

Thanks Monty, ok I am beginning to think some other page is causing this issue.
It seems something is eating up all the processing resources.

I just tested the page again and it worked fine this time, so I checked the event log for around the time there was issues publishing and I noticed this error.

"ISAPI 'C:\Windows\system32\inetsrv\asp.dll' reported itself as unhealthy for the following reason: 'ASP unhealthy because 97% of executing requests are hung and 9% of the request queue is full.'."
not sure if you saw this but it may help

http://support2.microsoft.com/kb/2734970/en-gb

have you seen an increase in traffic?
I think in this case, setting the server script time out is not going to help. The default is already 90 seconds although if your page is setting it to 60, the increase in time, if works, may just be a bandaid.

This sounds like a long time to generate a pdf.   I would start by getting the domain on a dedicated app pool if it is not already.  http://technet.microsoft.com/en-us/library/cc745955.aspx

I would also log into the server while a pdf generates and look at the amount of memory/cpu that is being eaten up.  

Look for some loops in your code that are not stopping as well.  Try adding some code that will write out some code or number before, during and after each loop and that could help pinpoint.
Avatar of Sevron

ASKER

Thanks Monty,
We have not seen much of an increase in traffic but we have recently moved over to a new server a few months ago.

I followed that link and changed the MinBytesPerSecond to a higher value and will see how it goes.

Scott, I agree it is an aweful long time to generate a PDF considering the page that its meant to render takes about a second.
The domain is on its own dedicated app pool.

The memory is fine we are only using about half of that available, the processor spikes occasionally so im wondering if that's when a pdf is generated.

I will have a look into creating a secondary duplicate page I can test with and print out some values as this page is live.

Thanks.
Have you confirmed it is the pdf creating that's causing the issue and not calls to the database?
Avatar of Sevron

ASKER

Hi Monty,

I am struggling to figure out if it is the creating of the PDF or the calls to the database as the issue is intermittent, it doesn't happen all the time only at certain times. To fix it usually we restart the site in IIS then the problem goes away for a while.

Is there anything else on the server that could cause the issue?
Is there anything else on the server that could cause the issue?

yes, a million things :) we could spend a lot of time just guessing, or we can do what we can to try to narrow down the issue. I prefer the second option :)

are you familiar with error handling in asp? it's a bit archaic, but may be useful in this situation. have a look at this link for a brief intro on error handling, then in your code, put the "on error resume next" statements couple with a check on Err.Number in different places in your code. if you have email capabilities on the site, it would be easiest to just send yourself an email whenever an error occurs, like:

if Err.Number <> 0 then
      '-- call email function
end if

any questions, just ask and I'll gladly help out.
Funny, that link on error handling seems to be throwing an error..

Why not isolate.  First, take out the actual creation of the pdf, but run a similar script that either sends data to a screen or writes to the server.  Then do the opposite, create the pdf with static data similar to what the database is outputting. Just don't do it via the database.

When you are running the data without writing to the pdf, try it by both calling the com object and without.

Also give error tracing a try http://technet.microsoft.com/en-us/library/cc731798(v=ws.10).aspx
Funny, that link on error handling seems to be throwing an error..

comes up perfectly fine for me, must be on your end
Must have been a short term thing.  There was a classic asp error that showed up, but works now.
Avatar of Sevron

ASKER

We have found that the we need to move the my sql database to another drive. The timeouts occur when other processes are using the drive.
ASKER CERTIFIED SOLUTION
Avatar of Big Monty
Big Monty
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial