1 | <html> |
---|
2 | <head> |
---|
3 | <title>libsm : Debugging and Tracing</title> |
---|
4 | </head> |
---|
5 | <body> |
---|
6 | |
---|
7 | <a href="index.html">Back to libsm overview</a> |
---|
8 | |
---|
9 | <center> |
---|
10 | <h1> libsm : Debugging and Tracing </h1> |
---|
11 | <br> $Id: debug.html,v 1.1.1.1 2003-04-08 15:06:57 zacheiss Exp $ |
---|
12 | </center> |
---|
13 | |
---|
14 | <h2> Introduction </h2> |
---|
15 | |
---|
16 | The debug and trace package provides abstractions for writing trace |
---|
17 | messages, and abstractions for enabling and disabling debug and |
---|
18 | trace code at run time. |
---|
19 | |
---|
20 | <p> |
---|
21 | Sendmail 8.11 and earlier has a <tt>-d</tt> option which |
---|
22 | lets you turn on debug and trace code. |
---|
23 | Debug categories are integers from 0 to 99, with the sole exception |
---|
24 | of "ANSI", which is a named debug category. |
---|
25 | |
---|
26 | <p> |
---|
27 | The libsm debug package supports named debug categories. |
---|
28 | Debug category names have the form of C identifiers. |
---|
29 | For example, <tt>sm_trace_heap</tt> controls the output of trace |
---|
30 | messages from the sm heap package, while <tt>sm_check_heap</tt> |
---|
31 | controls the argument validity checking and memory leak detection |
---|
32 | features of the sm heap package. |
---|
33 | |
---|
34 | <p> |
---|
35 | In sendmail 8.12, the <tt>-d</tt> flag is generalized |
---|
36 | to support both the original style numeric categories, for backwards |
---|
37 | compatibility, and the new style named categories implemented by libsm. |
---|
38 | With this change, |
---|
39 | "-dANSI" is implemented using a libsm named debug category. |
---|
40 | You will be able to set a collection of named debug categories to |
---|
41 | the same activation level by specifying a glob pattern. |
---|
42 | For example, |
---|
43 | <dl> |
---|
44 | <dt> |
---|
45 | <tt> -dANSI </tt> |
---|
46 | <dd> |
---|
47 | sets the named category "ANSI" to level 1, |
---|
48 | <dt> |
---|
49 | <tt> -dfoo_*.3 </tt> |
---|
50 | <dd> |
---|
51 | sets all named categories matching the glob pattern "foo_*" to level 3, |
---|
52 | <dt> |
---|
53 | <tt> -d0-99.1 </tt> |
---|
54 | <dd> |
---|
55 | sets the numeric categories 0 through 99 to level 1, and |
---|
56 | <dt> |
---|
57 | <tt> -dANSI,foo_*.3,0-99.1 </tt> |
---|
58 | <dd> |
---|
59 | does all of the above. |
---|
60 | </dl> |
---|
61 | |
---|
62 | <h2> Synopsis </h2> |
---|
63 | |
---|
64 | <pre> |
---|
65 | #include <sm/debug.h> |
---|
66 | |
---|
67 | /* |
---|
68 | ** abstractions for printing trace messages |
---|
69 | */ |
---|
70 | void sm_dprintf(char *fmt, ...) |
---|
71 | void sm_dflush() |
---|
72 | void sm_debug_setfile(SM_FILE_T *) |
---|
73 | |
---|
74 | /* |
---|
75 | ** abstractions for setting and testing debug activation levels |
---|
76 | */ |
---|
77 | void sm_debug_addsettings(char *settings) |
---|
78 | void sm_debug_addsetting(char *pattern, int level) |
---|
79 | |
---|
80 | typedef struct sm_debug SM_DEBUG_T; |
---|
81 | SM_DEBUG_T dbg = SM_DEBUG_INITIALIZER("name", "@(#)$Debug: name - description $"); |
---|
82 | |
---|
83 | bool sm_debug_active(SM_DEBUG_T *debug, int level) |
---|
84 | int sm_debug_level(SM_DEBUG_T *debug) |
---|
85 | bool sm_debug_unknown(SM_DEBUG_T *debug) |
---|
86 | </pre> |
---|
87 | |
---|
88 | <h2> Naming Conventions </h2> |
---|
89 | |
---|
90 | All debug categories defined by libsm have names of the form <tt>sm_*</tt>. |
---|
91 | Debug categories that turn on trace output have names of the form |
---|
92 | <tt>*_trace_*</tt>. |
---|
93 | Debug categories that turn on run time checks have names of the form |
---|
94 | <tt>*_check_*</tt>. |
---|
95 | Here are all of the libsm debug categories as of March 2000: |
---|
96 | |
---|
97 | <table> |
---|
98 | <tr> |
---|
99 | <td>Variable name</td> |
---|
100 | <td>Category name</td> |
---|
101 | <td>Meaning</td> |
---|
102 | </tr> |
---|
103 | <tr> |
---|
104 | <td>SmExpensiveAssert</td> |
---|
105 | <td>sm_check_assert</td> |
---|
106 | <td>enable expensive SM_ASSERT checking</td> |
---|
107 | </tr> |
---|
108 | <tr> |
---|
109 | <td>SmExpensiveRequire</td> |
---|
110 | <td>sm_check_require</td> |
---|
111 | <td>enable expensive SM_REQUIRE checking</td> |
---|
112 | </tr> |
---|
113 | <tr> |
---|
114 | <td>SmExpensiveEnsure</td> |
---|
115 | <td>sm_check_ensure</td> |
---|
116 | <td>enable expensive SM_ENSURE checking</td> |
---|
117 | </tr> |
---|
118 | <tr> |
---|
119 | <td>SmHeapTrace</td> |
---|
120 | <td>sm_trace_heap</td> |
---|
121 | <td>trace sm_{malloc,realloc,free} calls</td> |
---|
122 | </tr> |
---|
123 | <tr> |
---|
124 | <td>SmHeapCheck</td> |
---|
125 | <td>sm_check_heap</td> |
---|
126 | <td>enable checking and memory leak detection in sm_{malloc,realloc,free}</td> |
---|
127 | </tr> |
---|
128 | </table> |
---|
129 | |
---|
130 | <h2> Function Reference </h2> |
---|
131 | |
---|
132 | <dl> |
---|
133 | <dt> |
---|
134 | <tt> SM_DEBUG_INITIALIZER </tt> |
---|
135 | <dd> |
---|
136 | To create a new debug category, use the SM_DEBUG_INITIALIZER macro |
---|
137 | to initialize a static variable of type SM_DEBUG_T. For example, |
---|
138 | <blockquote><pre> |
---|
139 | SM_DEBUG_T ANSI_debug = SM_DEBUG_INITIALIZER("ANSI", |
---|
140 | "@(#)$Debug: ANSI - enable reverse video in debug output $"); |
---|
141 | </pre></blockquote> |
---|
142 | There is no centralized table of category names that needs to |
---|
143 | be edited in order to add a new debug category. |
---|
144 | The sole purpose of the second argument to SM_DEBUG_INITIALIZER |
---|
145 | is to provide an easy way to find out what named debug categories |
---|
146 | are present in a sendmail binary. You can use: |
---|
147 | <blockquote><pre> |
---|
148 | ident /usr/sbin/sendmail | grep Debug |
---|
149 | </pre></blockquote> |
---|
150 | or: |
---|
151 | <blockquote><pre> |
---|
152 | what /usr/sbin/sendmail | grep Debug |
---|
153 | </pre></blockquote> |
---|
154 | |
---|
155 | |
---|
156 | <dt> |
---|
157 | <tt> void sm_debug_addsetting(char *pattern, int level) </tt> |
---|
158 | <dd> |
---|
159 | All debug categories default to activation level 0, which means |
---|
160 | no activity. |
---|
161 | This function updates an internal database of debug settings, |
---|
162 | setting all categories whose name matches the specified glob |
---|
163 | pattern to the specified activation level. The level argument |
---|
164 | must be >= 0. |
---|
165 | <p> |
---|
166 | |
---|
167 | |
---|
168 | <dt> |
---|
169 | <tt> void sm_debug_addsettings(char *settings) </tt> |
---|
170 | <dd> |
---|
171 | This function is used to process the <tt>-d</tt> command line |
---|
172 | option of Sendmail 9.x, and of other programs that support the |
---|
173 | setting of named debug categories. The settings argument is a |
---|
174 | comma-separated list of settings; each setting is a glob pattern, |
---|
175 | optionally followed by a '.' and a decimal numeral. |
---|
176 | <p> |
---|
177 | |
---|
178 | |
---|
179 | <dt> |
---|
180 | <tt> bool sm_debug_active(SM_DEBUG_T *debug, int level) </tt> |
---|
181 | <dd> |
---|
182 | This macro returns <tt>true</tt> if the activation level of |
---|
183 | the statically initialized debug structure <tt>debug</tt> |
---|
184 | is >= the specified level. |
---|
185 | The test is performed very efficiently: in the most common case, |
---|
186 | when the result is <tt>false</tt>, only a single comparison |
---|
187 | operation is performed. |
---|
188 | <p> |
---|
189 | This macro performs a function call only if the debug structure has |
---|
190 | an unknown activation level. All debug structures are in this state |
---|
191 | at the beginning of program execution, and after a call to |
---|
192 | <tt>sm_debug_addsetting</tt>. |
---|
193 | <p> |
---|
194 | |
---|
195 | |
---|
196 | <dt> |
---|
197 | <tt> int sm_debug_level(SM_DEBUG_T *debug) </tt> |
---|
198 | <dd> |
---|
199 | This macro returns the activation level of the specified debug structure. |
---|
200 | The comparison |
---|
201 | <blockquote><pre> |
---|
202 | sm_debug_level(debug) >= level |
---|
203 | </pre></blockquote> |
---|
204 | is slightly less efficient than, but otherwise semantically |
---|
205 | equivalent to |
---|
206 | <blockquote><pre> |
---|
207 | sm_debug_active(debug, level) |
---|
208 | </pre></blockquote> |
---|
209 | <p> |
---|
210 | |
---|
211 | |
---|
212 | <dt> |
---|
213 | <tt> bool sm_debug_unknown(SM_DEBUG_T *debug) </tt> |
---|
214 | <dd> |
---|
215 | This macro returns true if the activation level of the specified |
---|
216 | debug structure is unknown. |
---|
217 | Here is an example of how the macro might be used: |
---|
218 | <blockquote><pre> |
---|
219 | if (sm_debug_unknown(&FooDebug)) |
---|
220 | { |
---|
221 | if (sm_debug_active(&FooDebug, 1)) |
---|
222 | { |
---|
223 | ... perform some expensive data structure initializations |
---|
224 | ... in order to enable the "foo" debugging mechanism |
---|
225 | } |
---|
226 | else |
---|
227 | { |
---|
228 | ... disable the "foo" debugging mechanism |
---|
229 | } |
---|
230 | } |
---|
231 | </pre></blockquote> |
---|
232 | The purpose of using <tt>sm_debug_unknown</tt> in the above example |
---|
233 | is to avoid performing the expensive initializations each time through |
---|
234 | the code. So it's a performance hack. |
---|
235 | A debug structure is in the "unknown" state at the beginning of |
---|
236 | program execution, and after a call to <tt>sm_debug_addsetting</tt>. |
---|
237 | A side effect of calling <tt>sm_debug_active</tt> is that the |
---|
238 | activation level becomes known. |
---|
239 | <p> |
---|
240 | |
---|
241 | |
---|
242 | <dt> |
---|
243 | <tt> void sm_dprintf(char *fmt, ...) </tt> |
---|
244 | <dd> |
---|
245 | This function is used to print a debug message. |
---|
246 | The standard idiom is |
---|
247 | <blockquote><pre> |
---|
248 | if (sm_debug_active(&BarDebug, 1)) |
---|
249 | sm_dprintf("bar: about to test tensile strength of bar %d\n", i); |
---|
250 | </pre></blockquote> |
---|
251 | <p> |
---|
252 | |
---|
253 | <dt> |
---|
254 | <tt> void sm_dflush() </tt> |
---|
255 | <dd> |
---|
256 | Flush the debug output stream. |
---|
257 | <p> |
---|
258 | |
---|
259 | <dt> |
---|
260 | <tt> void sm_debug_setfile(SM_FILE_T *file) </tt> |
---|
261 | <dd> |
---|
262 | This function lets you specify where debug output is printed. |
---|
263 | By default, debug output is written to standard output. |
---|
264 | <p> |
---|
265 | We want to allow you to direct debug output to syslog. |
---|
266 | The current plan is to provide a standard interface for |
---|
267 | creating an SM_FILE_T object that writes to syslog. |
---|
268 | |
---|
269 | </dl> |
---|
270 | |
---|
271 | </body> |
---|
272 | </html> |
---|