14a339480313e5b687eb899766347021ca94b41d
chmalee
  Thu Jul 30 16:12:03 2026 -0700
Call errCatchEnd() before handling the caught error in the tusd hooks, refs #37963

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

diff --git src/hg/hgHubConnect/hooks/pre-create.c src/hg/hgHubConnect/hooks/pre-create.c
index d731b6d29ee..e2dbde8f761 100644
--- src/hg/hgHubConnect/hooks/pre-create.c
+++ src/hg/hgHubConnect/hooks/pre-create.c
@@ -159,39 +159,41 @@
                         " issue with our server, please email genome-www@soe.ucsc.edu with your"
                         " userName so we can investigate.", reqFileName);
                 }
             struct hash *changeObjHash = hashNew(0);
             struct hash *pathObjHash = hashNew(0);
             struct jsonElement *changeObj = newJsonObject(changeObjHash);
             struct jsonElement *pathObj = newJsonObject(pathObjHash);
 
             jsonObjectAdd(pathObj, "Path", newJsonString(location));
             jsonObjectAdd(changeObj, "Storage", pathObj);
             jsonObjectAdd(changeObj, "ID", newJsonString(makeRandomKey(128)));
             jsonObjectAdd(response, "ChangeFileInfo", changeObj);
             fillOutHttpResponseSuccess(response);
             }
         }
+    // pop the handlers before handling the error, so an errAbort in the error
+    // path cannot longjmp back into this same block
+    errCatchEnd(errCatch);
     if (errCatch->gotError)
         {
         // App-level reject: tusd treats exit 0 + RejectUpload=true as a clean
         // rejection and forwards our HTTPResponse body verbatim. Non-zero
         // would be wrapped in "ERR_INTERNAL_SERVER_ERROR ... from hook
         // endpoint: ..." which buries the real message.
         rejectUpload(response, errCatch->message->string);
         exitStatus = 0;
         }
-    errCatchEnd(errCatch);
     }
 // always print a response no matter what
 jsonPrintToFile(response, NULL, stdout, 0);
 return 0;
 }
 
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 optionInit(&argc, argv, options);
 if (argc != 1)
     usage();
 return preCreate();
 }