Preface:
What is the expectation given to debugging: What is wrong in my source code. With Windbg, NTSD, debugging tools, you need to know some preparatory knowledge, so it is not conducive to promotion. Source code in front of the Apace Time I found some way to use some intentive way to position. Of course, Apache mainly used this method to collect some running data, with everyone ... first, the simplest one .... Write log files.
details:
In Apache, she redefines all Win32 APIs, some of whose key API, such as SOCK class API, Apache hopes to track their calls at any time to make it easy to determine the location of this error (location in source code) ) So for these API Apache, they are redefined:
/ ************************************************** ****************************
Socket is a Win32 API function, here it will be redefined
'/' Represents a newline in the source code
Spr_dbg_log is a function that records the Socket function of the call in the source code
__File __, __ line___ is a predefined macro in the Windows environment. Represents the current original file, line number, respectively.
*********************************************************** *************************** /
#define socket (i1, i2, i3) /
(Socket) APR_DBG_LOG ("Socket", /
(Handle) (Socket) (I1, I2, I3), /
__File __, __ line __, 0)))
The most important thing is the APR_DBG_LOG function, this function reflects the level of master: What should I do when considering the multi-threaded call to this function ... You need to pay attention to: "Because the function needs to be used in the macro Each function should be enclosed in parentheses. "As for the reason any C book, you will mention this right when it is said to macro."
Handle Apr_DBG_Log (CHAR * FN, // Function name of the tracked function
Handle Ha, // Trackful function return value
Char * fl, // __file__
INT LN, / / __LINE__
INT NH, / / APACHE For event, a signal function defined a indication variable, I checked the source code, send
// This parameter is now used in version 2.0.45, most of which use 0 as an incoming parameter.
...)
{
Static DWORD TLSID = 0xffffffffff;
Static Handle FH = NULL;
Static long CTR = 0;
Static critical_section cs;
Long seq;
DWORD WROTE;
Char * sbuf;
//
// SEQ records the number of functions indicated by the HA (in this example, a socket function) is called.
// is equivalent to a counter, in order to ensure that the count is still required to use the atomic operation API: InterlockedIncrement in the multi-threaded environment
/ / Of course, now this function has a new alternative function: InterlocKedexchangeAdd (see "Windows Core Programming" Chapter 8)
//
SEQ = (InterlockedIncrement) (& CTR);
IF (TLSID == 0xffffff) {
TLSID = (TLSalloc) ();
}
/ / Prevent buffer from being improperly rewritten in multiple thread calls (thread local storage)
// buffer and specific threads related ...
SBUF = (Char *) (TLSID) (TLSID);
IF (! fh ||! sbuf) {
SBUF = (char *) (Malloc) (1024);
(TLSSetValue) (TLSID, SBUF); SBUF [1023] = '/ 0';
IF (! fm) {
(GetModuleFileName) (NULL, SBUF, 250);
Sprintf (StrChr (SBUF, '/ 0'), ".% D", (GetCurrentProcessid) ());
// Create a log file, the file name prefix is the file name of the executable file, the suffix is the thread ID to ensure uniqueness.
FH = (createfile) (SBUF, Generic_Write, 0, Null, Create_always, 0, NULL);
Initialization (& CS);
}
}
When IF (! nh) // nh == 0
{
(Sprintf) (SBUF, "% 08X% 08X% 08X% S ()% s:% D / N", (DWORD) HA, SEQ, GetCurrentThreadID (), FN, FL, LN)
// Treatment of the above SEQ: In order to reach the synchronization problem in multi-thread, use the "critical code segment" mechanism to write logs to the file.
(EntercriticalSection) (& CS);
(WRITEFILE) (FH, SBUF, Strlen (SBUF), & wrote, NULL;
LeaveCriticalSection (& CS);
} // NH! = 0, this situation is very small, at least I found a few a few in WaitforsingleObject, in version 2.0.45
// used ... and it is not very clear that it meaning it, the motivation ... :-(
Else {
... // I don't know why this code has never been uploaded to 9CBS, ft!
}
Return HA;
}
Below is the Log Record of the function output
Returns the address called the number of ThreadID functions name this function (location in the source code)
Ffffffffff 00000001 0000024c socket () E: / mycode / analyze apache / APR_DBG_LOG / APR_DBG_LOG.CPP: 89
Ffffffffff 00000002 00000510 Socket () E: / mycode / analyze apache / APR_DBG_LOG / APR_DBG_LOG.CPP: 89
Ffffffffff 00000003 00000760 Socket () E: / mycode / analyze apache / APR_DBG_LOG / APR_DBG_LOG.CPP: 89
to sum up:
Sacrifice a little efficiency to change the simplicity of tracking problems.