2 This patch should fix the race condition that leads to a Director
3 crash at job end time when the job list is updated. This was reported
6 Apply this patch to Bacula version 2.4.2 (and earlier) with:
9 patch -p0 <2.4.2-jobend-crash.patch
10 ./configure <your-options>
17 ===================================================================
18 --- src/lib/jcr.c (revision 7627)
19 +++ src/lib/jcr.c (working copy)
21 void term_last_jobs_list()
24 + lock_last_jobs_list();
25 while (!last_jobs->empty()) {
26 void *je = last_jobs->first();
27 last_jobs->remove(je);
32 + unlock_last_jobs_list();
38 struct s_last_job *je, job;
42 Dmsg1(100, "read_last_jobs seek to %d\n", (int)addr);
43 if (addr == 0 || lseek(fd, (off_t)addr, SEEK_SET) < 0) {
45 if (num > 4 * max_last_jobs) { /* sanity check */
48 + lock_last_jobs_list();
50 if (read(fd, &job, sizeof(job)) != sizeof(job)) {
52 Pmsg1(000, "Read job entry. ERR=%s\n", be.bstrerror());
58 je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
64 + unlock_last_jobs_list();
68 uint64_t write_last_jobs_list(int fd, uint64_t addr)
70 struct s_last_job *je;
74 Dmsg1(100, "write_last_jobs seek to %d\n", (int)addr);
75 if (lseek(fd, (off_t)addr, SEEK_SET) < 0) {
79 + lock_last_jobs_list();
80 /* First record is number of entires */
81 num = last_jobs->size();
82 if (write(fd, &num, sizeof(num)) != sizeof(num)) {
84 Pmsg1(000, "Error writing num_items: ERR=%s\n", be.bstrerror());
88 foreach_dlist(je, last_jobs) {
89 if (write(fd, je, sizeof(struct s_last_job)) != sizeof(struct s_last_job)) {
91 Pmsg1(000, "Error writing job: ERR=%s\n", be.bstrerror());
96 + unlock_last_jobs_list();
98 /* Return current address */
99 - ssize_t stat = lseek(fd, 0, SEEK_CUR);
100 + stat = lseek(fd, 0, SEEK_CUR);
107 + unlock_last_jobs_list();
111 void lock_last_jobs_list()
113 last_job.end_time = time(NULL);
114 /* Keep list of last jobs, but not Console where JobId==0 */
115 if (last_job.JobId > 0) {
116 + lock_last_jobs_list();
117 je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
118 memcpy((char *)je, (char *)&last_job, sizeof(last_job));
121 last_jobs->remove(je);
124 + unlock_last_jobs_list();