HPCToolkit
fnbounds_client.c
Go to the documentation of this file.
1 // -*-Mode: C++;-*- // technically C99
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 // The client side of the new fnbounds server. Hpcrun creates a pipe
48 // and then forks and execs hpcfnbounds in server mode (-s). The file
49 // descriptors are passed as command-line arguments.
50 //
51 // This file implements the client side of the pipe. For each query,
52 // send the file name to the server. On success, mmap space for the
53 // answer, read the array of addresses from the pipe and read the
54 // extra info in the fnbounds file header. The file 'syserv-mesg.h'
55 // defines the API for messages over the pipe.
56 //
57 // Notes:
58 // 1. Automatically restart the server if it fails.
59 //
60 // 2. Automatically restart short reads. Reading from a pipe can
61 // return a short answer, especially if the other side buffers the
62 // writes.
63 //
64 // 3. Catch SIGPIPE. Writing to a pipe after the other side has
65 // exited triggers a SIGPIPE and terminates the process. It's
66 // important to catch (or ignore) SIGPIPE in the client so that if the
67 // server crashes, it doesn't also kill hpcrun.
68 //
69 // 4. We don't need to lock queries to the server. Calls to
70 // hpcrun_syserv_query() already hold the FNBOUNDS_LOCK.
71 //
72 // 5. Dup the hpcrun log file fd onto stdout and stderr to prevent
73 // stray output from the server.
74 //
75 // 6. The bottom of this file has code for an interactive, stand-alone
76 // client for testing hpcfnbounds in server mode.
77 //
78 // Todo:
79 //
80 
81 //***************************************************************************
82 
83 // To build an interactive, stand-alone client for testing:
84 // (1) turn on this #if and (2) fetch copies of syserv-mesg.h
85 // and fnbounds_file_header.h.
86 
87 #if 0
88 #define STAND_ALONE_CLIENT
89 #define EMSG(...)
90 #define EEMSG(...)
91 #define TMSG(...)
92 #define SAMPLE_SOURCES(...) zero_fcn()
93 #define dup2(...) zero_fcn()
94 #define hpcrun_set_disabled()
95 #define monitor_real_exit exit
96 #define monitor_real_fork fork
97 #define monitor_real_execve execve
98 #define monitor_sigaction(...) 0
99 int zero_fcn(void) { return 0; }
100 #endif
101 
102 //***************************************************************************
103 
104 #include <sys/types.h>
105 #include <sys/mman.h>
106 #include <sys/stat.h>
107 #include <sys/wait.h>
108 #include <err.h>
109 #include <errno.h>
110 #include <fcntl.h>
111 #include <signal.h>
112 #include <stdbool.h>
113 #include <stdint.h>
114 #include <stdio.h>
115 #include <stdlib.h>
116 #include <string.h>
117 #include <unistd.h>
118 
119 #if !defined(STAND_ALONE_CLIENT)
120 #include <hpcfnbounds/syserv-mesg.h>
121 #include "client.h"
122 #include "disabled.h"
123 #include "fnbounds_file_header.h"
124 #include "messages.h"
125 #include "sample_sources_all.h"
126 #include "monitor.h"
127 #else
128 #include "syserv-mesg.h"
129 #include "fnbounds_file_header.h"
130 #endif
131 
132 // Limit on memory use at which we restart the server in Meg.
133 #define SERVER_MEM_LIMIT 140
134 #define MIN_NUM_QUERIES 12
135 
136 #define SUCCESS 0
137 #define FAILURE -1
138 #define END_OF_FILE -2
139 
140 enum {
143 };
144 
146 static char *server;
147 
148 static int fdout = -1;
149 static int fdin = -1;
150 
151 static pid_t my_pid;
152 static pid_t server_pid = 0;
153 
154 // rusage units are Kbytes.
155 static long mem_limit = SERVER_MEM_LIMIT * 1024;
156 static int num_queries = 0;
157 static int mem_warning = 0;
158 
159 extern char **environ;
160 
161 
162 //*****************************************************************
163 // I/O helper functions
164 //*****************************************************************
165 
166 // Automatically restart short reads over a pipe.
167 // Returns: SUCCESS, FAILURE or END_OF_FILE.
168 //
169 static int
170 read_all(int fd, void *buf, size_t count)
171 {
172  ssize_t ret;
173  size_t len;
174 
175  len = 0;
176  while (len < count) {
177  ret = read(fd, ((char *) buf) + len, count - len);
178  if (ret < 0 && errno != EINTR) {
179  return FAILURE;
180  }
181  if (ret == 0) {
182  return END_OF_FILE;
183  }
184  if (ret > 0) {
185  len += ret;
186  }
187  }
188 
189  return SUCCESS;
190 }
191 
192 
193 // Automatically restart short writes over a pipe.
194 // Returns: SUCCESS or FAILURE.
195 //
196 static int
197 write_all(int fd, const void *buf, size_t count)
198 {
199  ssize_t ret;
200  size_t len;
201 
202  len = 0;
203  while (len < count) {
204  ret = write(fd, ((const char *) buf) + len, count - len);
205  if (ret < 0 && errno != EINTR) {
206  return FAILURE;
207  }
208  if (ret > 0) {
209  len += ret;
210  }
211  }
212 
213  return SUCCESS;
214 }
215 
216 
217 // Read a single syserv mesg from incoming pipe.
218 // Returns: SUCCESS, FAILURE or END_OF_FILE.
219 //
220 static int
221 read_mesg(struct syserv_mesg *mesg)
222 {
223  int ret;
224 
225  memset(mesg, 0, sizeof(*mesg));
226  ret = read_all(fdin, mesg, sizeof(*mesg));
227  if (ret == SUCCESS && mesg->magic != SYSERV_MAGIC) {
228  ret = FAILURE;
229  }
230 
231  return ret;
232 }
233 
234 
235 // Write a single syserv mesg to outgoing pipe.
236 // Returns: SUCCESS or FAILURE.
237 //
238 static int
239 write_mesg(int32_t type, int64_t len)
240 {
241  struct syserv_mesg mesg;
242 
243  mesg.magic = SYSERV_MAGIC;
244  mesg.type = type;
245  mesg.len = len;
246 
247  return write_all(fdout, &mesg, sizeof(mesg));
248 }
249 
250 
251 //*****************************************************************
252 // Mmap Helper Functions
253 //*****************************************************************
254 
255 // Returns: 'size' rounded up to a multiple of the mmap page size.
256 static size_t
257 page_align(size_t size)
258 {
259  static size_t pagesize = 0;
260 
261  if (pagesize == 0) {
262 #if defined(_SC_PAGESIZE)
263  long ans = sysconf(_SC_PAGESIZE);
264  if (ans > 0) {
265  pagesize = ans;
266  }
267 #endif
268  if (pagesize == 0) {
269  pagesize = 4096;
270  }
271  }
272 
273  return ((size + pagesize - 1)/pagesize) * pagesize;
274 }
275 
276 
277 // Returns: address of anonymous mmap() region, else MAP_FAILED on
278 // failure.
279 static void *
280 mmap_anon(size_t size)
281 {
282  int flags, prot;
283 
284  size = page_align(size);
285  prot = PROT_READ | PROT_WRITE;
286 #if defined(MAP_ANONYMOUS)
287  flags = MAP_PRIVATE | MAP_ANONYMOUS;
288 #else
289  flags = MAP_PRIVATE | MAP_ANON;
290 #endif
291 
292  return mmap(NULL, size, prot, flags, -1, 0);
293 }
294 
295 
296 //*****************************************************************
297 // Signal Handler
298 //*****************************************************************
299 
300 // Catch and ignore SIGPIPE so that if the server crashes it doesn't
301 // also kill hpcrun.
302 //
303 static int
304 hpcrun_sigpipe_handler(int sig, siginfo_t *info, void *context)
305 {
306  TMSG(SYSTEM_SERVER, "caught SIGPIPE: system server must have exited");
307  return 0;
308 }
309 
310 
311 //*****************************************************************
312 // Start and Stop the System Server
313 //*****************************************************************
314 
315 // Launch the server lazily.
316 
317 // Close our file descriptors to the server. If the server is still
318 // alive, it will detect end-of-file on read() from the pipe.
319 //
320 static void
322 {
323  close(fdout);
324  close(fdin);
325  fdout = -1;
326  fdin = -1;
328 
329  // collect the server's exit status to reduce zombies. but we must
330  // do it non-blocking and only for the fnbounds server, not any
331  // application child.
332  if (server_pid > 0) {
333  waitpid(server_pid, NULL, WNOHANG);
334  }
335  server_pid = 0;
336 
337  TMSG(SYSTEM_SERVER, "syserv shutdown");
338 }
339 
340 
341 // Returns: 0 on success, else -1 on failure.
342 static int
344 {
345  int sendfd[2], recvfd[2];
346  bool sampling_is_running;
347  pid_t pid;
348 
349  // already running
350  if (client_status == SYSERV_ACTIVE && my_pid == getpid()) {
351  return 0;
352  }
353 
354  // new process after fork
355  if (client_status == SYSERV_ACTIVE) {
356  shutdown_server();
357  }
358 
359  if (pipe(sendfd) != 0 || pipe(recvfd) != 0) {
360  EMSG("SYSTEM_SERVER ERROR: syserv launch failed: pipe failed");
361  return -1;
362  }
363 
364  // some sample sources need to be stopped in the parent, or else
365  // they cause problems in the child.
366  sampling_is_running = SAMPLE_SOURCES(started);
367  if (sampling_is_running) {
368  SAMPLE_SOURCES(stop);
369  }
370  pid = monitor_real_fork();
371 
372  if (pid < 0) {
373  //
374  // fork failed
375  //
376  EMSG("SYSTEM_SERVER ERROR: syserv launch failed: fork failed");
377  return -1;
378  }
379  else if (pid == 0) {
380  //
381  // child process: disable profiling, dup the log file fd onto
382  // stderr and exec hpcfnbounds in server mode.
383  //
385 
386  close(sendfd[1]);
387  close(recvfd[0]);
388 
389  // dup the hpcrun log file fd onto stdout and stderr.
390  if (dup2(messages_logfile_fd(), 1) < 0) {
391  warn("dup of log fd onto stdout failed");
392  }
393  if (dup2(messages_logfile_fd(), 2) < 0) {
394  warn("dup of log fd onto stderr failed");
395  }
396 
397  // make the command line and exec
398  char *arglist[8];
399  char fdin_str[10], fdout_str[10];
400  sprintf(fdin_str, "%d", sendfd[0]);
401  sprintf(fdout_str, "%d", recvfd[1]);
402 
403  arglist[0] = server;
404  arglist[1] = "-m";
405  arglist[2] = "-s";
406  arglist[3] = fdin_str;
407  arglist[4] = fdout_str;
408  arglist[5] = NULL;
409 
410  monitor_real_execve(server, arglist, environ);
411  err(1, "hpcrun system server: exec(%s) failed", server);
412  }
413 
414  //
415  // parent process: return and wait for queries.
416  //
417  close(sendfd[0]);
418  close(recvfd[1]);
419  fdout = sendfd[1];
420  fdin = recvfd[0];
421  my_pid = getpid();
422  server_pid = pid;
424  num_queries = 0;
425  mem_warning = 0;
426 
427  TMSG(SYSTEM_SERVER, "syserv launch: success, server: %d", (int) server_pid);
428 
429  // restart sample sources
430  if (sampling_is_running) {
431  SAMPLE_SOURCES(start);
432  }
433 
434  return 0;
435 }
436 
437 
438 // Returns: 0 on success, else -1 on failure.
439 int
441 {
442  TMSG(SYSTEM_SERVER, "syserv init");
443 
444  server = getenv("HPCRUN_FNBOUNDS_CMD");
445  if (server == NULL) {
446  EMSG("SYSTEM_SERVER ERROR: unable to get HPCRUN_FNBOUNDS_CMD");
447  return -1;
448  }
449 
450  // limit on server memory usage in Meg
451  char *str = getenv("HPCRUN_SERVER_MEMSIZE");
452  long size;
453  if (str == NULL || sscanf(str, "%ld", &size) < 1) {
454  size = SERVER_MEM_LIMIT;
455  }
456  mem_limit = size * 1024;
457 
458  if (monitor_sigaction(SIGPIPE, &hpcrun_sigpipe_handler, 0, NULL) != 0) {
459  EMSG("SYSTEM_SERVER ERROR: unable to install handler for SIGPIPE");
460  }
461 
462  launch_server();
463 
464  // check that the server answers ACK
465  struct syserv_mesg mesg;
466  if (write_mesg(SYSERV_ACK, 0) == SUCCESS && read_mesg(&mesg) == SUCCESS) {
467  return 0;
468  }
469 
470  // if not, then retry one time
471  shutdown_server();
472  launch_server();
473  if (write_mesg(SYSERV_ACK, 0) == SUCCESS && read_mesg(&mesg) == SUCCESS) {
474  return 0;
475  }
476 
477  // if we can't run the fnbounds server, then the profile is useless,
478  // so exit.
479  shutdown_server();
480  EEMSG("hpcrun: unable to launch the hpcfnbounds server.\n"
481  "hpcrun: check that hpctoolkit is properly configured with dyninst\n"
482  "and its prereqs (boost, elfutils, libdwarf, bzip, libz, lzma).");
483  monitor_real_exit(1);
484 
485  return -1;
486 }
487 
488 
489 void
491 {
492  // don't tell the server to exit unless we're the process that
493  // started it.
494  if (client_status == SYSERV_ACTIVE && my_pid == getpid()) {
496  }
497  shutdown_server();
498 
499  TMSG(SYSTEM_SERVER, "syserv fini");
500 }
501 
502 
503 //*****************************************************************
504 // Query the System Server
505 //*****************************************************************
506 
507 // Returns: pointer to array of void * and fills in the file header,
508 // or else NULL on error.
509 //
510 void *
511 hpcrun_syserv_query_specific(const char *fname, struct fnbounds_file_header *fh, int query)
512 {
513  struct syserv_mesg mesg;
514  void *addr;
515 
516  if (fname == NULL || fh == NULL) {
517  EMSG("SYSTEM_SERVER ERROR: passed NULL pointer to %s", __func__);
518  return NULL;
519  }
520 
521  if (client_status != SYSERV_ACTIVE || my_pid != getpid()) {
522  launch_server();
523  }
524 
525  TMSG(SYSTEM_SERVER, "query %d: %s", query, fname);
526 
527  // Send the file name length (including \0) to the server and look
528  // for the initial ACK. If the server has died, then make one
529  // attempt to restart it before giving up.
530  //
531  size_t len = strlen(fname) + 1;
532  if (write_mesg(query, len) != SUCCESS
533  || read_mesg(&mesg) != SUCCESS || mesg.type != SYSERV_ACK)
534  {
535  TMSG(SYSTEM_SERVER, "restart server");
536  shutdown_server();
537  launch_server();
538  if (write_mesg(query, len) != SUCCESS
539  || read_mesg(&mesg) != SUCCESS || mesg.type != SYSERV_ACK)
540  {
541  EMSG("SYSTEM_SERVER ERROR: unable to restart system server");
542  shutdown_server();
543  return NULL;
544  }
545  }
546 
547  // Send the file name (including \0) and wait for the initial answer
548  // (OK or ERR). At this point, errors are pretty much fatal.
549  //
550  if (write_all(fdout, fname, len) != SUCCESS) {
551  EMSG("SYSTEM_SERVER ERROR: lost contact with server");
552  shutdown_server();
553  return NULL;
554  }
555  if (read_mesg(&mesg) != SUCCESS) {
556  EMSG("SYSTEM_SERVER ERROR: lost contact with server");
557  shutdown_server();
558  return NULL;
559  }
560  if (mesg.type != SYSERV_OK) {
561  EMSG("SYSTEM_SERVER ERROR: query failed: %s", fname);
562  return NULL;
563  }
564 
565  // Mmap a region for the answer and read the array of addresses.
566  // Note: mesg.len is the number of addrs, not bytes.
567  //
568  size_t num_bytes = mesg.len * sizeof(void *);
569  size_t mmap_size = page_align(num_bytes);
570  addr = mmap_anon(mmap_size);
571  if (addr == MAP_FAILED) {
572  // Technically, we could keep the server alive in this case.
573  // But we would have to read all the data to stay in sync with
574  // the server.
575  EMSG("SYSTEM_SERVER ERROR: mmap failed");
576  shutdown_server();
577  return NULL;
578  }
579  if (read_all(fdin, addr, num_bytes) != SUCCESS) {
580  EMSG("SYSTEM_SERVER ERROR: lost contact with server");
581  shutdown_server();
582  return NULL;
583  }
584 
585  // Read the trailing fnbounds file header.
586  struct syserv_fnbounds_info fnb_info;
587  int ret = read_all(fdin, &fnb_info, sizeof(fnb_info));
588  if (ret != SUCCESS || fnb_info.magic != FNBOUNDS_MAGIC) {
589  EMSG("SYSTEM_SERVER ERROR: lost contact with server");
590  shutdown_server();
591  return NULL;
592  }
593  if (fnb_info.status != SYSERV_OK) {
594  EMSG("SYSTEM_SERVER ERROR: query failed: %s", fname);
595  return NULL;
596  }
597  fh->num_entries = fnb_info.num_entries;
598  fh->reference_offset = fnb_info.reference_offset;
599  fh->is_relocatable = fnb_info.is_relocatable;
600  fh->mmap_size = mmap_size;
601 
602  TMSG(SYSTEM_SERVER, "addr: %p, symbols: %ld, offset: 0x%lx, reloc: %d",
603  addr, (long) fh->num_entries, (long) fh->reference_offset,
604  (int) fh->is_relocatable);
605  TMSG(SYSTEM_SERVER, "server memsize: %ld Meg", fnb_info.memsize / 1024);
606 
607  // Restart the server if it's done a minimum number of queries and
608  // has exceeded its memory limit. Issue a warning at 60%.
609  num_queries++;
610  if (!mem_warning && fnb_info.memsize > (6 * mem_limit)/10) {
611  EMSG("SYSTEM_SERVER: warning: memory usage: %ld Meg",
612  fnb_info.memsize / 1024);
613  mem_warning = 1;
614  }
615  if (num_queries >= MIN_NUM_QUERIES && fnb_info.memsize > mem_limit) {
616  EMSG("SYSTEM_SERVER: warning: memory usage: %ld Meg, restart server",
617  fnb_info.memsize / 1024);
618  shutdown_server();
619  }
620 
621  return addr;
622 }
623 
624 void *
625 hpcrun_syserv_query(const char *fname, struct fnbounds_file_header *fh)
626 {
627  return hpcrun_syserv_query_specific(fname, fh, SYSERV_QUERY);
628 }
629 
630 void *
631 hpcrun_syserv_query_var(const char *fname, struct fnbounds_file_header *fh)
632 {
633  TMSG(SYSTEM_SERVER, "query variable for %s", fname);
635 }
636 
637 
638 //*****************************************************************
639 // Stand Alone Client
640 //*****************************************************************
641 
642 #ifdef STAND_ALONE_CLIENT
643 
644 #define BUF_SIZE 2000
645 
646 static void
647 query_loop(void)
648 {
649  struct fnbounds_file_header fnb_hdr;
650  char fname[BUF_SIZE];
651  void **addr;
652  long k;
653 
654  for (;;) {
655  printf("\nfnbounds> ");
656  if (fgets(fname, BUF_SIZE, stdin) == NULL) {
657  break;
658  }
659  char *new_line = strchr(fname, '\n');
660  if (new_line != NULL) {
661  *new_line = 0;
662  }
663 
664  addr = (void **) hpcrun_syserv_query(fname, &fnb_hdr);
665 
666  if (addr == NULL) {
667  printf("error\n");
668  }
669  else {
670  for (k = 0; k < fnb_hdr.num_entries; k++) {
671  printf(" %p\n", addr[k]);
672  }
673  printf("num symbols = %ld, offset = 0x%lx, reloc = %d\n",
674  fnb_hdr.num_entries, fnb_hdr.reference_offset,
675  fnb_hdr.is_relocatable);
676 
677  if (munmap(addr, fnb_hdr.mmap_size) != 0) {
678  err(1, "munmap failed");
679  }
680  }
681  }
682 }
683 
684 
685 int
686 main(int argc, char *argv[])
687 {
688  struct sigaction act;
689 
690  if (argc < 2) {
691  errx(1, "usage: client /path/to/fnbounds");
692  }
693  server = argv[1];
694 
695  memset(&act, 0, sizeof(act));
696  act.sa_handler = SIG_IGN;
697  sigemptyset(&act.sa_mask);
698  if (sigaction(SIGPIPE, &act, NULL) != 0) {
699  err(1, "sigaction failed on SIGPIPE");
700  }
701 
702  if (launch_server() != 0) {
703  errx(1, "fnbounds server failed");
704  }
705  printf("server: %s\n", server);
706  printf("parent: %d, child: %d\n", my_pid, server_pid);
707  printf("connected\n");
708 
709  query_loop();
710 
712 
713  printf("done\n");
714  return 0;
715 }
716 
717 #endif // STAND_ALONE_CLIENT
ssize_t MONITOR_EXT_WRAP_NAME() write(int fd, const void *buf, size_t count)
Definition: io-over.c:189
static int launch_server(void)
void * hpcrun_syserv_query_specific(const char *fname, struct fnbounds_file_header *fh, int query)
#define SAMPLE_SOURCES(op,...)
static int read_mesg(struct syserv_mesg *mesg)
#define MIN_NUM_QUERIES
static long mem_limit
static void * mmap_anon(size_t size)
void * hpcrun_syserv_query(const char *fname, struct fnbounds_file_header *fh)
err
Definition: names.cpp:1
static char * server
static void shutdown_server(void)
static int mem_warning
#define SERVER_MEM_LIMIT
static size_t page_align(size_t size)
int messages_logfile_fd(void)
Definition: fmt.c:108
static int write_all(int fd, const void *buf, size_t count)
#define BUF_SIZE
Definition: PGMReader.cpp:101
#define FNBOUNDS_MAGIC
Definition: syserv-mesg.h:63
static int client_status
#define FAILURE
#define SYSERV_MAGIC
Definition: syserv-mesg.h:62
void hpcrun_set_disabled(void)
Definition: disabled.c:87
static int read_all(int fd, void *buf, size_t count)
static __thread u32 pid
#define SUCCESS
char ** environ
#define EMSG
Definition: messages.h:70
int64_t len
Definition: syserv-mesg.h:77
void hpcrun_syserv_fini(void)
static int fdout
int main(int argc, char *argv[])
Definition: main.cpp:125
#define END_OF_FILE
static int fdin
int32_t type
Definition: syserv-mesg.h:76
int hpcrun_syserv_init(void)
#define TMSG(f,...)
Definition: messages.h:93
void * hpcrun_syserv_query_var(const char *fname, struct fnbounds_file_header *fh)
unsigned long reference_offset
static size_t pagesize
Definition: mem.c:84
int32_t magic
Definition: syserv-mesg.h:75
ssize_t MONITOR_EXT_WRAP_NAME() read(int fd, void *buf, size_t count)
Definition: io-over.c:152
static int num_queries
#define EEMSG(...)
Definition: messages.h:90
#define NULL
Definition: ElfHelper.cpp:85
static int write_mesg(int32_t type, int64_t len)
static int hpcrun_sigpipe_handler(int sig, siginfo_t *info, void *context)
cct_addr_t * addr
Definition: cct.c:130
errx
Definition: names.cpp:1
static pid_t my_pid
uint64_t reference_offset
Definition: syserv-mesg.h:88
static pid_t server_pid