|
58 | 58 | #include "storage/pg_shmem.h"
|
59 | 59 | #include "storage/pmsignal.h"
|
60 | 60 | #include "storage/procsignal.h"
|
| 61 | +#include "utils/ascii.h" |
61 | 62 | #include "utils/guc.h"
|
62 | 63 | #include "utils/memutils.h"
|
63 | 64 | #include "utils/ps_status.h"
|
@@ -2228,6 +2229,7 @@ static PgBackendStatus *MyBEEntry = NULL;
|
2228 | 2229 | static char *BackendClientHostnameBuffer = NULL;
|
2229 | 2230 | static char *BackendAppnameBuffer = NULL;
|
2230 | 2231 | static char *BackendActivityBuffer = NULL;
|
| 2232 | +static Size BackendActivityBufferSize = 0; |
2231 | 2233 |
|
2232 | 2234 |
|
2233 | 2235 | /*
|
@@ -2310,9 +2312,12 @@ CreateSharedBackendStatus(void)
|
2310 | 2312 | }
|
2311 | 2313 |
|
2312 | 2314 | /* Create or attach to the shared activity buffer */
|
2313 |
| - size = mul_size(pgstat_track_activity_query_size, MaxBackends); |
| 2315 | + BackendActivityBufferSize = mul_size(pgstat_track_activity_query_size, |
| 2316 | + MaxBackends); |
2314 | 2317 | BackendActivityBuffer = (char *)
|
2315 |
| - ShmemInitStruct("Backend Activity Buffer", size, &found); |
| 2318 | + ShmemInitStruct("Backend Activity Buffer", |
| 2319 | + BackendActivityBufferSize, |
| 2320 | + &found); |
2316 | 2321 |
|
2317 | 2322 | if (!found)
|
2318 | 2323 | {
|
@@ -2751,6 +2756,70 @@ pgstat_get_backend_current_activity(int pid, bool checkUser)
|
2751 | 2756 | return "<backend information not available>";
|
2752 | 2757 | }
|
2753 | 2758 |
|
| 2759 | +/* ---------- |
| 2760 | + * pgstat_get_crashed_backend_activity() - |
| 2761 | + * |
| 2762 | + * Return a string representing the current activity of the backend with |
| 2763 | + * the specified PID. Like the function above, but reads shared memory with |
| 2764 | + * the expectation that it may be corrupt. Returns either a pointer to a |
| 2765 | + * constant string, or writes into the 'buffer' argument and returns it. |
| 2766 | + * |
| 2767 | + * This function is only intended to be used by postmaster to report the |
| 2768 | + * query that crashed the backend. In particular, no attempt is made to |
| 2769 | + * follow the correct concurrency protocol when accessing the |
| 2770 | + * BackendStatusArray. But that's OK, in the worst case we'll return a |
| 2771 | + * corrupted message. We also must take care not to trip on ereport(ERROR). |
| 2772 | + * |
| 2773 | + * Note: return strings for special cases match pg_stat_get_backend_activity. |
| 2774 | + * ---------- |
| 2775 | + */ |
| 2776 | +const char * |
| 2777 | +pgstat_get_crashed_backend_activity(int pid, char *buffer, |
| 2778 | + int len) |
| 2779 | +{ |
| 2780 | + volatile PgBackendStatus *beentry; |
| 2781 | + int i; |
| 2782 | + |
| 2783 | + beentry = BackendStatusArray; |
| 2784 | + for (i = 1; i <= MaxBackends; i++) |
| 2785 | + { |
| 2786 | + if (beentry->st_procpid == pid) |
| 2787 | + { |
| 2788 | + /* Read pointer just once, so it can't change after validation */ |
| 2789 | + const char *activity = beentry->st_activity; |
| 2790 | + const char *activity_last; |
| 2791 | + |
| 2792 | + /* |
| 2793 | + * We can't access activity pointer before we verify that it |
| 2794 | + * falls into BackendActivityBuffer. To make sure that the entire |
| 2795 | + * string including its ending is contained within the buffer, |
| 2796 | + * we subtract one activity length from it. |
| 2797 | + */ |
| 2798 | + activity_last = BackendActivityBuffer + BackendActivityBufferSize |
| 2799 | + - pgstat_track_activity_query_size; |
| 2800 | + |
| 2801 | + if (activity < BackendActivityBuffer || |
| 2802 | + activity > activity_last) |
| 2803 | + return "<command string corrupt>"; |
| 2804 | + |
| 2805 | + if (*(activity) == '\0') |
| 2806 | + return "<command string empty>"; |
| 2807 | + |
| 2808 | + /* |
| 2809 | + * Copy only ASCII-safe characters so we don't run into encoding |
| 2810 | + * problems when reporting the message. |
| 2811 | + */ |
| 2812 | + ascii_safe_strncpy(buffer, activity, len); |
| 2813 | + |
| 2814 | + return buffer; |
| 2815 | + } |
| 2816 | + |
| 2817 | + beentry++; |
| 2818 | + } |
| 2819 | + |
| 2820 | + /* PID not found */ |
| 2821 | + return "<backend information not available>"; |
| 2822 | +} |
2754 | 2823 |
|
2755 | 2824 | /* ------------------------------------------------------------
|
2756 | 2825 | * Local support functions follow
|
|
0 commit comments