35 #include <sys/syscall.h>
44 #if defined(__linux__) || defined(__APPLE__)
45 #define TidType long long
47 #elif defined(__GNU__)
48 #define TidType pthread_t
51 #define TidType pthread_t
67 static const int iniDepth =15;
68 static const int maxDepth =30;
69 static const int xeqDepth =32;
71 static const int ptrXORFilter = 1;
74 std::vector<void *> *ptrFilter[2] = {0, 0};
86 struct XrdInfo {
const char *name;
int code;
int mask;};
88 XrdInfo *CvtReq(
const char *name,
int rnum)
90 static XrdInfo reqTab[] = {{
"auth",
kXR_auth, 1 },
121 static XrdInfo unkTab = {
"n/a",-1,-1};
127 {
if (rnum < kXR_auth || rnum >
kXR_truncate)
return &unkTab;
133 for (
int i = 0; i < reqNum; i++)
134 {
if (!strcmp(name, reqTab[i].name))
return &reqTab[i];}
145 XrdInfo *CvtRsp(
const char *name,
int snum)
147 static XrdInfo rspTab[] = {{
"oksofar",
kXR_oksofar, 1<< 1},
155 static XrdInfo aokTab = {
"ok", 0, 1};
156 static XrdInfo unkTab = {
"n/a", -1,-1};
162 {
if (!snum)
return &aokTab;
163 if (snum < kXR_oksofar || snum >
kXR_waitresp)
return &unkTab;
169 for (
int i = 0; i < rspNum; i++)
170 {
if (!strcmp(name, rspTab[i].name))
return &rspTab[i];}
182 int Demangle(
char *cSym,
char *buff,
int blen)
185 char *plus = index(cSym,
'+');
186 char *brak = (plus ? index(plus,
'[') : 0);
187 char *cpar = (plus ? index(plus,
')') : 0);
190 if (*cSym !=
'(' || !plus || !cpar || !brak)
191 return snprintf(buff, blen,
"%s\n", cSym);
194 realname = abi::__cxa_demangle(cSym+1, 0, 0, &status);
196 if (status) {*plus =
'+';
return snprintf(buff, blen,
"%s\n", cSym);}
199 status = snprintf(buff, blen,
"%s %s+%s\n", brak, realname, plus+1);
213 char *theDepth = getenv(
"XRDBT_DEPTH");
214 int depth = iniDepth;
216 if (theDepth && (depth = atoi(theDepth)) <= 0) depth = iniDepth;
218 return (depth <= maxDepth ? depth : maxDepth);
229 void DumpStack(
char *bP,
int bL,
TidType tid)
232 snprintf(bP, bL,
"TBT " TidFmt " No stack information available with musl libc.", tid);
235 static int btDepth = DumpDepth();
237 char *cStack[xeqDepth];
238 int k, n = backtrace((
void **)cStack, xeqDepth);
242 if (n > 1) cSyms = backtrace_symbols((
void **)cStack, n);
243 else {snprintf(bP, bL,
"TBT " TidFmt " No stack information available.", tid);
249 if (n > btDepth) n = btDepth+1;
250 for (
int i = 2; i < n && bL > 24; i++)
251 {
char *paren = index(cSyms[i],
'(');
252 if (!paren) k = snprintf(bP, bL,
"TBT " TidFmt " %s\n", tid, cSyms[i]);
253 else {k = snprintf(bP, bL,
"TBT " TidFmt " ", tid);
255 k = Demangle(paren, bP, bL);
270 bool Screen(
void *thisP,
void *objP,
bool rrOK)
273 std::vector<void *>::const_iterator it;
274 std::vector<void *> *objV, *thsV;
280 {
for (it = objV->begin(); it!= objV->end(); ++it)
281 if (objP == *it)
return true;
288 {
for (it = thsV->begin(); it!= thsV->end(); ++it)
289 if (thisP == *it)
return true;
294 if ((objV && objV->size()) && (thsV && thsV->size()))
return false;
310 const char *tail,
bool force)
319 {
if (
AtomicGet(xeqPtrFilter) && !Screen(thisP, objP,
false))
return;}
323 if (!head) head =
"";
324 if (!tail) tail =
"";
325 #if defined(__linux__) || defined(__APPLE__)
326 tid = syscall(SYS_gettid);
333 k = snprintf(btBuff,
sizeof(btBuff),
"\nTBT " TidFmt " %p %s obj %p %s\n",
334 tid, thisP, head, objP, tail);
338 DumpStack(btBuff+k,
sizeof(btBuff)-k-8, tid);
342 std::cerr <<btBuff <<std::flush;
358 if (reqs || (reqs = getenv(
"XRDBT_REQFILTER")))
359 {line = strdup(reqs);
363 {infoP = CvtReq(token, 0);
364 if (infoP->code > 0) reqFilter |= infoP->mask;
372 if (rsps || (rsps = getenv(
"XRDBT_RSPFILTER")))
373 {line = strdup(rsps);
377 {infoP = CvtRsp(token, 0);
378 if (infoP->code > 0) rspFilter |= infoP->mask;
397 std::vector<void *>::iterator it;
398 std::vector<void *> *filtP;
402 filtP = ptrFilter[pType];
408 {filtP =
new std::vector<void *>();
409 filtP->push_back(ptr);
410 ptrFilter[pType] = filtP;
419 {
int i = pType ^ ptrXORFilter;
421 if (!ptrFilter[i] || ptrFilter[i]->size() == 0)
AtomicZAP(xeqPtrFilter);
429 filtP->push_back(ptr);
436 for (it = filtP->begin(); it!= filtP->end(); ++it)
if (ptr == *it)
break;
440 if (it != filtP->end())
442 {
int i = pType ^ ptrXORFilter;
444 if (filtP->size() == 0 && (!ptrFilter[i] || !(ptrFilter[i]->size())))
446 std::cerr <<
"delIt: " <<xeqPtrFilter <<std::endl;
454 {filtP->push_back(ptr);
465 const char *tail,
bool force)
467 XrdInfo *infoP, *reqInfo, *rspInfo;
476 {
if (!reqFilter && !rspFilter) rrOK =
false;
477 else if (reqFilter && (infoP=CvtReq(0, reqN))
478 && !(reqFilter & infoP->mask)) rrOK =
false;
479 else if (rspFilter && (infoP=CvtRsp(0, rspN))
480 && !(rspFilter & infoP->mask)) rrOK =
false;
482 if (
AtomicGet(xeqPtrFilter)) {
if (!Screen(thisP, objP, rrOK))
return;}
483 else if (!rrOK)
return;
488 if (!head) head =
"";
489 if (!tail) tail =
"";
490 reqInfo = CvtReq(0, reqN);
491 rspInfo = CvtRsp(0, rspN);
492 #if defined(__linux__) || defined(__APPLE__)
493 tid = syscall(SYS_gettid);
500 k = snprintf(btBuff,
sizeof(btBuff),
501 "\nTBT " TidFmt " %p %s obj %p req %s rsp %s %s\n",
502 tid, thisP, head, objP, reqInfo->name, rspInfo->name, tail);
506 DumpStack(btBuff+k,
sizeof(btBuff)-k-8, tid);
510 std::cerr <<btBuff <<std::flush;
PtrType
Define filter types and actions.
@ isObject
Pointer is an object pointer.
@ isThis
Pointer is a this pointer.
static void Filter(void *ptr, PtrType pType, Action how=addIt)
static bool Init(const char *reqs=0, const char *rsps=0)
@ repIt
Replace all PtrTypes items filtered with this item.
@ delIt
Delete this item from the list of PtrTypes filtered.
@ addIt
Add item to the list of PtrTypes being filtered.
@ clrIt
Delete all PtrType filtered items (1st arg ignored).
static void XrdBT(const char *head=0, void *thisP=0, void *objP=0, int rspN=0, int reqN=0, const char *tail=0, bool force=false)
static void DoBT(const char *head=0, void *thisP=0, void *objP=0, const char *tail=0, bool force=false)
char * GetToken(char **rest=0, int lowcase=0)
static pthread_t ID(void)