V(jcr_lock);
}
-/*
- * This function should be used only after receiving a violent signal
- * We walk through the JCR chain without doing any lock, bacula should
- * not be running.
- */
-void print_jcr_dbg()
-{
- char buf1[128], buf2[128], buf3[128], buf4[128];
-
- if (!jcrs) {
- return;
- }
-
- fprintf(stderr, "Attempt to dump current JCRs\n");
-
- for (JCR *jcr = (JCR *)jcrs->first(); jcr ; jcr = (JCR *)jcrs->next(jcr)) {
- if (!jcr) { /* protect us against something ? */
- continue;
- }
-
- fprintf(stderr, "JCR=%p JobId=%i name=%s JobStatus=%c\n",
- jcr, jcr->JobId, jcr->Job, jcr->JobStatus);
- fprintf(stderr, "\tuse_count=%i threadid=0x%x\n",
- jcr->use_count(), (int)jcr->my_thread_id);
- fprintf(stderr, "\tJobType=%c JobLevel=%c\n",
- jcr->get_JobType(), jcr->get_JobLevel());
- bstrftime(buf1, sizeof(buf1), jcr->sched_time);
- bstrftime(buf2, sizeof(buf2), jcr->start_time);
- bstrftime(buf3, sizeof(buf3), jcr->end_time);
- bstrftime(buf4, sizeof(buf4), jcr->wait_time);
- fprintf(stderr, "\tsched_time=%s start_time=%s\n\tend_time=%s wait_time=%s\n",
- buf1, buf2, buf3, buf4);
- fprintf(stderr, "\tdequeing=%i\n", jcr->dequeuing);
- fprintf(stderr, "\tdb=%p db_batch=%p batch_started=%i\n",
- jcr->db, jcr->db_batch, jcr->batch_started);
- }
-}
-
/*
* Start walk of jcr chain
* The proper way to walk the jcr chain is:
{
return; /* thus interrupting the function */
}
+
+/*
+ * !!! WARNING !!!
+ *
+ * This function should be used ONLY after a violent signal. We walk through the
+ * JCR chain without doing any lock, bacula should not be running.
+ */
+void _print_jcr_dbg(FILE *fp)
+{
+ char buf1[128], buf2[128], buf3[128], buf4[128];
+ if (!jcrs) {
+ return;
+ }
+
+ fprintf(fp, "Attempt to dump current JCRs\n");
+
+ for (JCR *jcr = (JCR *)jcrs->first(); jcr ; jcr = (JCR *)jcrs->next(jcr)) {
+ if (!jcr) { /* protect us against something ? */
+ continue;
+ }
+
+ fprintf(fp, "JCR=%p JobId=%i name=%s JobStatus=%c\n",
+ jcr, jcr->JobId, jcr->Job, jcr->JobStatus);
+ fprintf(fp, "\tuse_count=%i threadid=0x%x\n",
+ jcr->use_count(), (int)jcr->my_thread_id);
+ fprintf(fp, "\tJobType=%c JobLevel=%c\n",
+ jcr->get_JobType(), jcr->get_JobLevel());
+ bstrftime(buf1, sizeof(buf1), jcr->sched_time);
+ bstrftime(buf2, sizeof(buf2), jcr->start_time);
+ bstrftime(buf3, sizeof(buf3), jcr->end_time);
+ bstrftime(buf4, sizeof(buf4), jcr->wait_time);
+ fprintf(fp, "\tsched_time=%s start_time=%s\n\tend_time=%s wait_time=%s\n",
+ buf1, buf2, buf3, buf4);
+ fprintf(fp, "\tdequeing=%i\n", jcr->dequeuing);
+ fprintf(fp, "\tdb=%p db_batch=%p batch_started=%i\n",
+ jcr->db, jcr->db_batch, jcr->batch_started);
+ }
+}
+
}
}
+/*
+ * Global variables to get information about lock/unlock db access
+ */
+utime_t _db_lock_time = 0;
+int _db_lock_recurse_count = 0;
+pthread_t _db_lock_threadid;
+
+static void print_lock_dbg(FILE *fp)
+{
+ char buf[128];
+ bstrutime(buf, sizeof(buf), _db_lock_time);
+
+ fprintf(fp, "lock info: recurse_count=%i threadid=0x%x time=%s\n",
+ _db_lock_recurse_count, (int)_db_lock_threadid, buf);
+}
+
+/* defined in jcr.c */
+extern void _print_jcr_dbg(FILE *fp);
+
+/*
+ * !!! WARNING !!!
+ *
+ * This function should be used ONLY after a violent signal. We walk through the
+ * JCR chain without doing any lock, bacula should not be running.
+ */
+static void print_bacula_dbg()
+{
+ char buf[512];
+
+ snprintf(buf, sizeof(buf), "%s/bacula.%d.bactrace",
+ working_directory, getpid());
+ FILE *fp = fopen(buf, "ab") ;
+ if (!fp) {
+ fp = stderr;
+ }
+
+ _print_jcr_dbg(fp);
+ print_lock_dbg(fp);
+
+ if (fp != stderr) {
+ fclose(fp);
+ }
+}
+
/*
* Handle signals here
*/
waitpid(pid, NULL, 0); /* wait for child to produce dump */
Dmsg0(500, "Done waitpid\n");
fprintf(stderr, _("Traceback complete, attempting cleanup ...\n"));
- /* print information about the current state into stderr */
- print_lock_dbg();
- print_jcr_dbg();
+ /* print information about the current state into working/<file>.bactrace */
+ print_bacula_dbg();
exit_handler(sig); /* clean up if possible */
Dmsg0(500, "Done exit_handler\n");
} else {