ASF Bugzilla – Attachment 32688 Details for
Bug 57501
abort_page does not stop page execution after a call to ::rivet::parse
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Error handling further improved
file_57501.txt (text/plain), 8.52 KB, created by
Massimo Manghi
on 2015-04-27 15:20:35 UTC
(
hide
)
Description:
Error handling further improved
Filename:
MIME Type:
Creator:
Massimo Manghi
Created:
2015-04-27 15:20:35 UTC
Size:
8.52 KB
patch
obsolete
>Index: src/apache-2/mod_rivet.c >=================================================================== >--- src/apache-2/mod_rivet.c (revision 1675418) >+++ src/apache-2/mod_rivet.c (working copy) >@@ -101,6 +101,32 @@ > > mod_rivet_globals* rivet_module_globals = NULL; > >+/* -- Rivet_PrintErrorMessage >+ * >+ * Utility function to print the error message stored in errorInfo >+ * with a custom header. This procedure is called to print standard >+ * errors when one of Tcl scripts fails >+ * >+ * Arguments: >+ * >+ * - Tcl_Interp* interp: the Tcl interpreter that was running the script >+ * (and therefore the built-in variable errorInfo >+ * keeps the message) >+ * - const char* error: Custom error header >+ */ >+ >+static void >+Rivet_PrintErrorMessage (Tcl_Interp* interp,const char* error_header) >+{ >+ Tcl_Obj* errormsg = Tcl_NewObj(); >+ >+ Tcl_IncrRefCount(errormsg); >+ Tcl_AppendStringsToObj(errormsg,"puts \"",error_header,"<br />\"\n",NULL); >+ Tcl_AppendStringsToObj(errormsg,"puts \"<pre>$errorInfo</pre>\"\n",NULL); >+ Tcl_EvalObjEx(interp,errormsg,0); >+ Tcl_DecrRefCount(errormsg); >+} >+ > /* > * -- Rivet_chdir_file (const char* filename) > * >@@ -299,6 +325,59 @@ > } > } > >+/* -- Rivet_ExecuteErrorHandler >+ * >+ * Invoking either the default error handler or the ErrorScript. >+ * In case the error handler fails a standard error message is printed >+ * (you're better off if you make your error handlers fail save) >+ * >+ * Arguments: >+ * >+ * - Tcl_Interp* interp: the Tcl interpreter >+ * - Tcl_Obj* tcl_script_obj: the script that failed (to retrieve error >+ * info from it >+ * - request_rec* req: current request obj pointer >+ * >+ * Returned value: >+ * >+ * - A Tcl status >+ */ >+ >+static int >+Rivet_ExecuteErrorHandler (Tcl_Interp* interp,Tcl_Obj* tcl_script_obj, request_rec* req) >+{ >+ int result; >+ rivet_server_conf* conf = Rivet_GetConf(req); >+ Tcl_Obj* errscript; >+ >+ /* We extract information from the errorOutbuf variable. Notice that tcl_script_obj >+ * can either be the request processing script or conf->rivet_abort_script >+ */ >+ >+ Tcl_SetVar( interp, "errorOutbuf",Tcl_GetStringFromObj( tcl_script_obj, NULL ),TCL_GLOBAL_ONLY ); >+ >+ /* If we don't have an error script, use the default error handler. */ >+ if (conf->rivet_error_script) { >+ errscript = conf->rivet_error_script; >+ } else { >+ errscript = conf->rivet_default_error_script; >+ } >+ >+ Tcl_IncrRefCount(errscript); >+ result = Tcl_EvalObjEx(interp, errscript, 0); >+ if (result == TCL_ERROR) { >+ Rivet_PrintErrorMessage(interp,"<b>Rivet ErrorScript failed</b>"); >+ } >+ >+ /* This shouldn't make the default_error_script go away, >+ * because it gets a Tcl_IncrRefCount when it is created. >+ */ >+ Tcl_DecrRefCount(errscript); >+ >+ return result; >+} >+ >+ > /* -- Rivet_ExecuteAndCheck > * > * Tcl script execution central procedure. The script stored >@@ -316,7 +395,8 @@ > * > * Returned value: > * >- * - invariably TCL_OK >+ * - One of the Tcl defined returned value of Tcl_EvelObjExe (TCL_OK, >+ * TCL_ERROR, TCL_BREAK etc.) > * > * Side effects: > * >@@ -330,7 +410,6 @@ > { > int result; > rivet_server_conf* conf = Rivet_GetConf(req); >- rivet_interp_globals* globals = Tcl_GetAssocData(interp, "rivet", NULL); > > Tcl_Preserve (interp); > result = Tcl_EvalObjEx(interp, tcl_script_obj, 0); >@@ -337,7 +416,6 @@ > > if (result == TCL_ERROR) { > >- Tcl_Obj* errscript; > Tcl_Obj* errorCodeListObj; > Tcl_Obj* errorCodeElementObj; > char* errorCodeSubString; >@@ -376,39 +454,54 @@ > { > if (conf->rivet_abort_script) > { >- if (Tcl_EvalObjEx(interp,conf->rivet_abort_script,0) == TCL_ERROR) >+ >+ /* Ideally an AbortScript should be fail safe, but in case >+ * it fails we give a chance to the subsequent ErrorScript >+ * to catch this error. >+ */ >+ >+ result = Tcl_EvalObjEx(interp,conf->rivet_abort_script,0); >+ if (result == TCL_ERROR) > { >- CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 ); >- TclWeb_PrintError("<b>Rivet AbortScript failed!</b>",1,globals->req); >- TclWeb_PrintError(errorinfo,0,globals->req); >+ >+ /* This is not elegant, but we want to avoid to print >+ * this error message if an ErrorScript will handle this error. >+ * Thus we print the usual error message only if we are running the >+ * default error handler >+ */ >+ >+ if (conf->rivet_error_script == NULL) { >+ >+ Rivet_PrintErrorMessage(interp,"<b>Rivet AbortScript failed</b>"); >+ } >+ else >+ { >+ result = Rivet_ExecuteErrorHandler(interp,conf->rivet_abort_script,req); >+ } > } > } >- goto good; >+ else >+ { >+ >+ /* If the script issued a ::rivet::abort_page but no AbortScript was >+ * defined we return a TCL_OK anyway >+ */ >+ >+ result = TCL_OK; >+ >+ } > } > } >+ else >+ { >+ /* Invoke Rivet error handler */ > >- Tcl_SetVar( interp, "errorOutbuf",Tcl_GetStringFromObj( tcl_script_obj, NULL ),TCL_GLOBAL_ONLY ); >+ result = Rivet_ExecuteErrorHandler(interp,tcl_script_obj,req); > >- /* If we don't have an error script, use the default error handler. */ >- if (conf->rivet_error_script) { >- errscript = conf->rivet_error_script; >- } else { >- errscript = conf->rivet_default_error_script; > } > >- Tcl_IncrRefCount(errscript); >- if (Tcl_EvalObjEx(interp, errscript, 0) == TCL_ERROR) { >- CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 ); >- TclWeb_PrintError("<b>Rivet ErrorScript failed!</b>",1,globals->req); >- TclWeb_PrintError( errorinfo, 0, globals->req ); >- } > >- /* This shouldn't make the default_error_script go away, >- * because it gets a Tcl_IncrRefCount when it is created. */ >- Tcl_DecrRefCount(errscript); > } >- >-good: > > /* Tcl_Flush moved to the end of Rivet_SendContent */ > >@@ -425,7 +518,12 @@ > * if a Tcl script. > * > * This is a separate function so that it may be called from command 'parse' >+ * >+ * Returned value: > * >+ * - One of the Tcl defined values returned by Rivet_ExecuteAndCheck (TCL_OK, >+ * TCL_ERROR, TCL_BREAK etc.) >+ * > * Arguments: > * > * - TclWebRequest: pointer to the structure collecting Tcl and Apache data >@@ -434,6 +532,7 @@ > * - toplevel: integer to be interpreted as a boolean meaning the > * file is pointed by the request. When 0 that's a subtemplate > * to be parsed and executed from another template >+ * > */ > > int >@@ -443,7 +542,7 @@ > int isNew = 0; > int result = 0; > >- Tcl_Obj *outbuf = NULL; >+ Tcl_Obj *outbuf = NULL; > Tcl_HashEntry *entry = NULL; > > time_t ctime; >@@ -1477,7 +1576,7 @@ > if (Rivet_ParseExecFile(globals->req, r->filename, 1) != TCL_OK) > { > ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r->server, >- MODNAME ": Error parsing exec file '%s': %s", >+ MODNAME ": Error in Rivet_ParseExecFile exec file '%s': %s", > r->filename, > Tcl_GetVar(interp, "errorInfo", 0)); > } >@@ -1488,9 +1587,7 @@ > { > if (Rivet_ExecuteAndCheck(interp, rsc->after_every_script,r) == TCL_ERROR) > { >- CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 ); >- TclWeb_PrintError("<b>Rivet AfterEveryScript failed!</b>",1,globals->req); >- TclWeb_PrintError( errorinfo, 0, globals->req ); >+ Rivet_PrintErrorMessage(interp,"<b>Rivet AfterEveryScript failed</b>"); > } > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 57501
:
32403
|
32404
|
32406
|
32659
|
32672
|
32688
|
32709
|
32713