* GetErrorContextStack - Return the context stack, for display/diags * * Returns a pstrdup'd string in the caller's context which includes the PG * error call stack. It is the caller's responsibility to ensure this string * is pfree'd (or its context cleaned up) when done. * * This information is collected by traversing the error contexts and calling * each context's callback function, eac
| 2300 | * errcontext() to return a string which can be presented to the user. |
| 2301 | */ |
| 2302 | char * |
| 2303 | GetErrorContextStack(void) |
| 2304 | { |
| 2305 | ErrorData *edata; |
| 2306 | ErrorContextCallback *econtext; |
| 2307 | |
| 2308 | /* |
| 2309 | * Okay, crank up a stack entry to store the info in. |
| 2310 | */ |
| 2311 | recursion_depth++; |
| 2312 | |
| 2313 | if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE) |
| 2314 | { |
| 2315 | /* |
| 2316 | * Wups, stack not big enough. We treat this as a PANIC condition |
| 2317 | * because it suggests an infinite loop of errors during error |
| 2318 | * recovery. |
| 2319 | */ |
| 2320 | errordata_stack_depth = -1; /* make room on stack */ |
| 2321 | ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded"))); |
| 2322 | } |
| 2323 | |
| 2324 | /* |
| 2325 | * Things look good so far, so initialize our error frame |
| 2326 | */ |
| 2327 | edata = &errordata[errordata_stack_depth]; |
| 2328 | MemSet(edata, 0, sizeof(ErrorData)); |
| 2329 | |
| 2330 | /* |
| 2331 | * Set up assoc_context to be the caller's context, so any allocations |
| 2332 | * done (which will include edata->context) will use their context. |
| 2333 | */ |
| 2334 | edata->assoc_context = CurrentMemoryContext; |
| 2335 | |
| 2336 | /* |
| 2337 | * Call any context callback functions to collect the context information |
| 2338 | * into edata->context. |
| 2339 | * |
| 2340 | * Errors occurring in callback functions should go through the regular |
| 2341 | * error handling code which should handle any recursive errors, though we |
| 2342 | * double-check above, just in case. |
| 2343 | */ |
| 2344 | for (econtext = error_context_stack; |
| 2345 | econtext != NULL; |
| 2346 | econtext = econtext->previous) |
| 2347 | econtext->callback(econtext->arg); |
| 2348 | |
| 2349 | /* |
| 2350 | * Clean ourselves off the stack, any allocations done should have been |
| 2351 | * using edata->assoc_context, which we set up earlier to be the caller's |
| 2352 | * context, so we're free to just remove our entry off the stack and |
| 2353 | * decrement recursion depth and exit. |
| 2354 | */ |
| 2355 | errordata_stack_depth--; |
| 2356 | recursion_depth--; |
| 2357 | |
| 2358 | /* |
| 2359 | * Return a pointer to the string the caller asked for, which should have |
no test coverage detected