HPCToolkit
messages-sync.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 //*****************************************************************************
48 // File: messages-sync.c
49 //
50 // Description:
51 // This half of the messaging system. It contains parts that need not be
52 // async-signal safe.
53 //
54 // History:
55 // 19 July 2009
56 // created by partitioning pmsg.c into pmsg-sync.c and pmsg-async.c
57 //
58 //*****************************************************************************
59 
60 
61 //*****************************************************************************
62 // global includes
63 //*****************************************************************************
64 
65 #include <fcntl.h>
66 #include <stdarg.h>
67 #include <stddef.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <sys/param.h>
72 #include <sys/types.h>
73 #include <sys/stat.h>
74 #include <unistd.h>
75 #include <stdbool.h>
76 
77 
78 
79 //*****************************************************************************
80 // local includes
81 //*****************************************************************************
82 
83 #include "disabled.h"
84 #include "fname_max.h"
85 #include "files.h"
86 #include "name.h"
87 #include "rank.h"
88 #include "thread_data.h"
89 #include "thread_use.h"
90 #include "monitor.h"
91 
92 #include <messages/debug-flag.h>
93 #include <messages/messages.h>
94 #include <messages/messages.i>
95 #include <messages/fmt.h>
96 
97 
98 //*****************************************************************************
99 // global variables
100 //*****************************************************************************
101 
102 FILE *log_file;
103 
104 
105 //*****************************************************************************
106 // file local (static) variables
107 //*****************************************************************************
108 
109 //-------------------------------------
110 // Log output may be throttled by using
111 // the message limiting mechanism
112 //-------------------------------------
113 static int global_msg_count = 0;
114 
115 //-------------------------------------
116 // how many unwind msg blocks to permit
117 // (500 is reasonable choice)
118 // FIXME: make this an option
119 //-------------------------------------
120 static int const threshold = 500;
121 
122 static int log_file_fd = 2; // initially log_file is stderr
123 
124 //*****************************************************************************
125 // forward declarations
126 //*****************************************************************************
127 
128 
129 //*****************************************************************************
130 // interface operations
131 //*****************************************************************************
132 
133 void
135 {
136  debug_flag_init();
137  global_msg_count = 0;
138 
139  spinlock_unlock(&pmsg_lock); // initialize lock for async operations
140 
141  log_file = stderr;
142  log_file_fd = 2; // std unix stderr
143 }
144 
145 
146 void
148 {
149  if (hpcrun_get_disabled()) return;
150 
151  // open log file
152  if (getenv("HPCRUN_LOG_STDERR") != NULL) {
153  // HPCRUN_LOG_STDERR variable set ==> log goes to stderr
154  log_file_fd = 2;
155  }
156  else {
157  // Normal case of opening .log file.
159  }
160  if (log_file_fd == -1) {
161  log_file_fd = 2; // cannot open log_file ==> revert to stderr
162  }
163 }
164 
165 
166 void
168 {
169  if (hpcrun_get_disabled()) return;
170 
171  if (log_file_fd != 2) {
172  int rv = close(log_file_fd);
173  if (rv) {
174  char *mesg = "hpctoolkit warning: unable to access log file "
175  "(maybe application closed the file descriptor)\n";
176  write(2, mesg, strlen(mesg));
177  }
178  //----------------------------------------------------------------------
179  // if this is an execution of an MPI program, we opened the log file
180  // before the MPI rank was known. thus, the name of the log file is
181  // missing the MPI rank. fix that now by renaming the log file to what
182  // it should be.
183  //----------------------------------------------------------------------
184  int rank = hpcrun_get_rank();
185  if (rank >= 0) {
187  }
188  }
189 }
190 
191 
192 void
193 hpcrun_exit_on_error(int ret, int ret_expected, const char *fmt, ...)
194 {
195  if (ret == ret_expected) {
196  return;
197  }
198  va_list_box box;
199  va_list_box_start(box, fmt);
200  hpcrun_write_msg_to_log(false, false, NULL, fmt, &box);
201  abort();
202 }
203 
204 
205 void
206 hpcrun_abort_w_info(void (*info)(void), const char *fmt, ...)
207 {
208  // massage fmt string to end in a newline
209  char fstr[MSG_BUF_SIZE];
210 
211  fstr[0] = '\0';
212  strncat(fstr, fmt, MSG_BUF_SIZE - strlen(fstr) - 5);
213  strcat(fstr,"\n");
214 
215  va_list_box box;
216 
217  if (log_file != stderr) {
218  va_list_box_start(box, fmt);
219  hpcrun_write_msg_to_log(false, false, NULL, fmt, &box);
220  }
221 
222  char buf[1024] = "";
223  va_list_box_start(box, fmt);
224  hpcrun_msg_vns(buf, sizeof(buf), fstr, &box);
225  write(2, buf, strlen(buf));
226  va_list_box_end(box);
227  info();
228  monitor_real_exit(-1);
229 }
230 
231 // message to log file, also echo on stderr
232 void
233 hpcrun_stderr_log_msg(bool copy_to_log, const char *fmt, ...)
234 {
235  // massage fmt string to end in a newline
236  char fstr[MSG_BUF_SIZE];
237  va_list_box box;
238 
239  fstr[0] = '\0';
240  strncat(fstr, fmt, MSG_BUF_SIZE - 5);
241  strcat(fstr,"\n");
242 
243  char buf[2048] = "";
244  va_list_box_start(box, fmt);
245  hpcrun_msg_vns(buf, sizeof(buf), fstr, &box);
246  write(2, buf, strlen(buf));
247  va_list_box_end(box);
248 
249  if (copy_to_log && log_file != stderr){
250  va_list_box_start(box, fmt);
251  hpcrun_write_msg_to_log(false, false, NULL, fmt, &box);
252  }
253 }
254 
255 
256 void
258 {
259 }
260 
261 
262 int
264 {
265  return log_file_fd;
266 }
267 
268 
269 int
271 {
272  return (global_msg_count < threshold);
273 }
274 
275 
276 void
278 {
280 }
281 
#define va_list_box_end(box)
Definition: fmt.h:57
ssize_t MONITOR_EXT_WRAP_NAME() write(int fd, const void *buf, size_t count)
Definition: io-over.c:189
int hpcrun_msg_vns(char *buf, size_t len, const char *fmt, va_list_box *box)
Definition: fmt.c:477
void debug_flag_init()
Definition: debug-flag.c:194
void messages_logfile_create()
static void spinlock_unlock(spinlock_t *l)
Definition: spinlock.h:96
int messages_logfile_fd(void)
void hpcrun_stderr_log_msg(bool copy_to_log, const char *fmt,...)
#define va_list_box_start(box, arg)
Definition: fmt.h:56
int hpcrun_below_pmsg_threshold(void)
abort
Definition: names.cpp:1
Definition: fmt.c:108
void hpcrun_exit_on_error(int ret, int ret_expected, const char *fmt,...)
void hpcrun_up_pmsg_count(void)
void hpcrun_abort_w_info(void(*info)(void), const char *fmt,...)
static int global_msg_count
int hpcrun_open_log_file(void)
Definition: files.c:432
void messages_init()
void messages_donothing(void)
int hpcrun_get_rank(void)
Definition: rank.c:89
void hpcrun_write_msg_to_log(bool echo_stderr, bool add_thread_id, const char *tag, const char *fmt, va_list_box *box)
int hpcrun_rename_log_file(int rank)
Definition: files.c:500
#define NULL
Definition: ElfHelper.cpp:85
FILE * log_file
static int log_file_fd
static int const threshold
bool hpcrun_get_disabled(void)
Definition: disabled.c:80
spinlock_t pmsg_lock
void messages_fini(void)