PostgreSQL Source Code  git master
ps_status.c File Reference
#include "postgres.h"
#include <unistd.h>
#include "libpq/libpq.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "utils/guc.h"
#include "utils/ps_status.h"
Include dependency graph for ps_status.c:

Go to the source code of this file.

Macros

#define PS_USE_NONE
 
#define PS_PADDING   ' '
 

Functions

char ** save_ps_display_args (int argc, char **argv)
 
void init_ps_display (const char *fixed_part)
 
void set_ps_display_suffix (const char *suffix)
 
void set_ps_display_remove_suffix (void)
 
void set_ps_display_with_len (const char *activity, size_t len)
 
const char * get_ps_display (int *displen)
 

Variables

char ** environ
 
bool update_process_title = DEFAULT_UPDATE_PROCESS_TITLE
 
static int save_argc
 
static char ** save_argv
 

Macro Definition Documentation

◆ PS_PADDING

#define PS_PADDING   ' '

Definition at line 68 of file ps_status.c.

◆ PS_USE_NONE

#define PS_USE_NONE

Definition at line 60 of file ps_status.c.

Function Documentation

◆ get_ps_display()

const char* get_ps_display ( int *  displen)

Definition at line 505 of file ps_status.c.

506 {
507 #ifdef PS_USE_CLOBBER_ARGV
508  /* If ps_buffer is a pointer, it might still be null */
509  if (!ps_buffer)
510  {
511  *displen = 0;
512  return "";
513  }
514 #endif
515 
516 #ifndef PS_USE_NONE
517  *displen = (int) (ps_buffer_cur_len - ps_buffer_fixed_size);
518 
519  return ps_buffer + ps_buffer_fixed_size;
520 #else
521  *displen = 0;
522  return "";
523 #endif
524 }

Referenced by log_status_format(), write_csvlog(), and write_jsonlog().

◆ init_ps_display()

void init_ps_display ( const char *  fixed_part)

Definition at line 242 of file ps_status.c.

243 {
244 #ifndef PS_USE_NONE
245  bool save_update_process_title;
246 #endif
247 
248  Assert(fixed_part || MyBackendType);
249  if (!fixed_part)
250  fixed_part = GetBackendTypeDesc(MyBackendType);
251 
252 #ifndef PS_USE_NONE
253  /* no ps display for stand-alone backend */
254  if (!IsUnderPostmaster)
255  return;
256 
257  /* no ps display if you didn't call save_ps_display_args() */
258  if (!save_argv)
259  return;
260 
261 #ifdef PS_USE_CLOBBER_ARGV
262  /* If ps_buffer is a pointer, it might still be null */
263  if (!ps_buffer)
264  return;
265 
266  /* make extra argv slots point at end_of_area (a NUL) */
267  for (int i = 1; i < save_argc; i++)
268  save_argv[i] = ps_buffer + ps_buffer_size;
269 #endif /* PS_USE_CLOBBER_ARGV */
270 
271  /*
272  * Make fixed prefix of ps display.
273  */
274 
275 #if defined(PS_USE_SETPROCTITLE) || defined(PS_USE_SETPROCTITLE_FAST)
276 
277  /*
278  * apparently setproctitle() already adds a `progname:' prefix to the ps
279  * line
280  */
281 #define PROGRAM_NAME_PREFIX ""
282 #else
283 #define PROGRAM_NAME_PREFIX "postgres: "
284 #endif
285 
286  if (*cluster_name == '\0')
287  {
288  snprintf(ps_buffer, ps_buffer_size,
289  PROGRAM_NAME_PREFIX "%s ",
290  fixed_part);
291  }
292  else
293  {
294  snprintf(ps_buffer, ps_buffer_size,
295  PROGRAM_NAME_PREFIX "%s: %s ",
296  cluster_name, fixed_part);
297  }
298 
299  ps_buffer_cur_len = ps_buffer_fixed_size = strlen(ps_buffer);
300 
301  /*
302  * On the first run, force the update.
303  */
304  save_update_process_title = update_process_title;
305  update_process_title = true;
306  set_ps_display("");
307  update_process_title = save_update_process_title;
308 #endif /* not PS_USE_NONE */
309 }
bool IsUnderPostmaster
Definition: globals.c:116
char * cluster_name
Definition: guc_tables.c:537
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
const char * GetBackendTypeDesc(BackendType backendType)
Definition: miscinit.c:264
BackendType MyBackendType
Definition: miscinit.c:64
#define snprintf
Definition: port.h:238
static int save_argc
Definition: ps_status.c:100
bool update_process_title
Definition: ps_status.c:31
static char ** save_argv
Definition: ps_status.c:101
static void set_ps_display(const char *activity)
Definition: ps_status.h:40

References Assert(), cluster_name, GetBackendTypeDesc(), i, IsUnderPostmaster, MyBackendType, save_argc, save_argv, set_ps_display(), snprintf, and update_process_title.

Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), AuxiliaryProcessMain(), BackendInitialize(), BackgroundWorkerMain(), ReplSlotSyncWorkerMain(), and SysLoggerMain().

◆ save_ps_display_args()

char** save_ps_display_args ( int  argc,
char **  argv 
)

Definition at line 118 of file ps_status.c.

119 {
120  save_argc = argc;
121  save_argv = argv;
122 
123 #if defined(PS_USE_CLOBBER_ARGV)
124 
125  /*
126  * If we're going to overwrite the argv area, count the available space.
127  * Also move the environment to make additional room.
128  */
129  {
130  char *end_of_area = NULL;
131  char **new_environ;
132  int i;
133 
134  /*
135  * check for contiguous argv strings
136  */
137  for (i = 0; i < argc; i++)
138  {
139  if (i == 0 || end_of_area + 1 == argv[i])
140  end_of_area = argv[i] + strlen(argv[i]);
141  }
142 
143  if (end_of_area == NULL) /* probably can't happen? */
144  {
145  ps_buffer = NULL;
146  ps_buffer_size = 0;
147  return argv;
148  }
149 
150  /*
151  * check for contiguous environ strings following argv
152  */
153  for (i = 0; environ[i] != NULL; i++)
154  {
155  if (end_of_area + 1 == environ[i])
156  end_of_area = environ[i] + strlen(environ[i]);
157  }
158 
159  ps_buffer = argv[0];
160  last_status_len = ps_buffer_size = end_of_area - argv[0];
161 
162  /*
163  * move the environment out of the way
164  */
165  new_environ = (char **) malloc((i + 1) * sizeof(char *));
166  if (!new_environ)
167  {
168  write_stderr("out of memory\n");
169  exit(1);
170  }
171  for (i = 0; environ[i] != NULL; i++)
172  {
173  new_environ[i] = strdup(environ[i]);
174  if (!new_environ[i])
175  {
176  write_stderr("out of memory\n");
177  exit(1);
178  }
179  }
180  new_environ[i] = NULL;
181  environ = new_environ;
182  }
183 
184  /*
185  * If we're going to change the original argv[] then make a copy for
186  * argument parsing purposes.
187  *
188  * (NB: do NOT think to remove the copying of argv[], even though
189  * postmaster.c finishes looking at argv[] long before we ever consider
190  * changing the ps display. On some platforms, getopt() keeps pointers
191  * into the argv array, and will get horribly confused when it is
192  * re-called to analyze a subprocess' argument string if the argv storage
193  * has been clobbered meanwhile. Other platforms have other dependencies
194  * on argv[].
195  */
196  {
197  char **new_argv;
198  int i;
199 
200  new_argv = (char **) malloc((argc + 1) * sizeof(char *));
201  if (!new_argv)
202  {
203  write_stderr("out of memory\n");
204  exit(1);
205  }
206  for (i = 0; i < argc; i++)
207  {
208  new_argv[i] = strdup(argv[i]);
209  if (!new_argv[i])
210  {
211  write_stderr("out of memory\n");
212  exit(1);
213  }
214  }
215  new_argv[argc] = NULL;
216 
217 #if defined(__darwin__)
218 
219  /*
220  * macOS has a static copy of the argv pointer, which we may fix like
221  * so:
222  */
223  *_NSGetArgv() = new_argv;
224 #endif
225 
226  argv = new_argv;
227  }
228 #endif /* PS_USE_CLOBBER_ARGV */
229 
230  return argv;
231 }
#define write_stderr(str)
Definition: parallel.c:184
#define malloc(a)
Definition: header.h:50
exit(1)
char ** environ

References environ, exit(), i, malloc, save_argc, save_argv, and write_stderr.

Referenced by main().

◆ set_ps_display_remove_suffix()

void set_ps_display_remove_suffix ( void  )

Definition at line 396 of file ps_status.c.

397 {
398 #ifndef PS_USE_NONE
399  /* first, check if we need to update the process title */
400  if (!update_ps_display_precheck())
401  return;
402 
403  /* check we added a suffix */
404  if (ps_buffer_nosuffix_len == 0)
405  return; /* no suffix */
406 
407  /* remove the suffix from ps_buffer */
408  ps_buffer[ps_buffer_nosuffix_len] = '\0';
409  ps_buffer_cur_len = ps_buffer_nosuffix_len;
410  ps_buffer_nosuffix_len = 0;
411 
412  Assert(ps_buffer_cur_len == strlen(ps_buffer));
413 
414  /* and set the new title */
415  flush_ps_display();
416 #endif /* not PS_USE_NONE */
417 }

References Assert().

Referenced by LockBufferForCleanup(), ResolveRecoveryConflictWithVirtualXIDs(), SyncRepWaitForLSN(), and WaitOnLock().

◆ set_ps_display_suffix()

void set_ps_display_suffix ( const char *  suffix)

Definition at line 344 of file ps_status.c.

345 {
346 #ifndef PS_USE_NONE
347  size_t len;
348 
349  /* first, check if we need to update the process title */
350  if (!update_ps_display_precheck())
351  return;
352 
353  /* if there's already a suffix, overwrite it */
354  if (ps_buffer_nosuffix_len > 0)
355  ps_buffer_cur_len = ps_buffer_nosuffix_len;
356  else
357  ps_buffer_nosuffix_len = ps_buffer_cur_len;
358 
359  len = strlen(suffix);
360 
361  /* check if we have enough space to append the suffix */
362  if (ps_buffer_cur_len + len + 1 >= ps_buffer_size)
363  {
364  /* not enough space. Check the buffer isn't full already */
365  if (ps_buffer_cur_len < ps_buffer_size - 1)
366  {
367  /* append a space before the suffix */
368  ps_buffer[ps_buffer_cur_len++] = ' ';
369 
370  /* just add what we can and fill the ps_buffer */
371  memcpy(ps_buffer + ps_buffer_cur_len, suffix,
372  ps_buffer_size - ps_buffer_cur_len - 1);
373  ps_buffer[ps_buffer_size - 1] = '\0';
374  ps_buffer_cur_len = ps_buffer_size - 1;
375  }
376  }
377  else
378  {
379  ps_buffer[ps_buffer_cur_len++] = ' ';
380  memcpy(ps_buffer + ps_buffer_cur_len, suffix, len + 1);
381  ps_buffer_cur_len = ps_buffer_cur_len + len;
382  }
383 
384  Assert(strlen(ps_buffer) == ps_buffer_cur_len);
385 
386  /* and set the new title */
387  flush_ps_display();
388 #endif /* not PS_USE_NONE */
389 }
const void size_t len

References Assert(), and len.

Referenced by LockBufferForCleanup(), ResolveRecoveryConflictWithVirtualXIDs(), SyncRepWaitForLSN(), and WaitOnLock().

◆ set_ps_display_with_len()

void set_ps_display_with_len ( const char *  activity,
size_t  len 
)

Definition at line 426 of file ps_status.c.

427 {
428  Assert(strlen(activity) == len);
429 
430 #ifndef PS_USE_NONE
431  /* first, check if we need to update the process title */
432  if (!update_ps_display_precheck())
433  return;
434 
435  /* wipe out any suffix when the title is completely changed */
436  ps_buffer_nosuffix_len = 0;
437 
438  /* Update ps_buffer to contain both fixed part and activity */
439  if (ps_buffer_fixed_size + len >= ps_buffer_size)
440  {
441  /* handle the case where ps_buffer doesn't have enough space */
442  memcpy(ps_buffer + ps_buffer_fixed_size, activity,
443  ps_buffer_size - ps_buffer_fixed_size - 1);
444  ps_buffer[ps_buffer_size - 1] = '\0';
445  ps_buffer_cur_len = ps_buffer_size - 1;
446  }
447  else
448  {
449  memcpy(ps_buffer + ps_buffer_fixed_size, activity, len + 1);
450  ps_buffer_cur_len = ps_buffer_fixed_size + len;
451  }
452  Assert(strlen(ps_buffer) == ps_buffer_cur_len);
453 
454  /* Transmit new setting to kernel, if necessary */
455  flush_ps_display();
456 #endif /* not PS_USE_NONE */
457 }

References Assert(), and len.

Referenced by exec_execute_message(), exec_simple_query(), and set_ps_display().

Variable Documentation

◆ environ

char** environ
extern

◆ save_argc

int save_argc
static

Definition at line 100 of file ps_status.c.

Referenced by init_ps_display(), and save_ps_display_args().

◆ save_argv

char** save_argv
static

Definition at line 101 of file ps_status.c.

Referenced by init_ps_display(), and save_ps_display_args().

◆ update_process_title