]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/2.4.2-jobend-crash.patch
Apply Joao's patch to SQLite tables to make chars work.
[bacula/bacula] / bacula / patches / 2.4.2-jobend-crash.patch
1
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
4  in bug #1162.
5
6  Apply this patch to Bacula version 2.4.2 (and earlier) with:
7
8  cd <bacula-source>
9  patch -p0 <2.4.2-jobend-crash.patch
10  ./configure <your-options>
11  make
12  ...
13  make install
14
15
16 Index: src/lib/jcr.c
17 ===================================================================
18 --- src/lib/jcr.c       (revision 7627)
19 +++ src/lib/jcr.c       (working copy)
20 @@ -110,6 +110,7 @@
21  void term_last_jobs_list()
22  {
23     if (last_jobs) {
24 +      lock_last_jobs_list();
25        while (!last_jobs->empty()) {
26           void *je = last_jobs->first();
27           last_jobs->remove(je);
28 @@ -117,6 +118,7 @@
29        }
30        delete last_jobs;
31        last_jobs = NULL;
32 +      unlock_last_jobs_list();
33     }
34     if (jcrs) {
35        delete jcrs;
36 @@ -128,6 +130,7 @@
37  {
38     struct s_last_job *je, job;
39     uint32_t num;
40 +   bool ok = true;
41  
42     Dmsg1(100, "read_last_jobs seek to %d\n", (int)addr);
43     if (addr == 0 || lseek(fd, (off_t)addr, SEEK_SET) < 0) {
44 @@ -140,11 +143,13 @@
45     if (num > 4 * max_last_jobs) {  /* sanity check */
46        return false;
47     }
48 +   lock_last_jobs_list();
49     for ( ; num; num--) {
50        if (read(fd, &job, sizeof(job)) != sizeof(job)) {
51           berrno be;
52           Pmsg1(000, "Read job entry. ERR=%s\n", be.bstrerror());
53 -         return false;
54 +         ok = false;
55 +         break;
56        }
57        if (job.JobId > 0) {
58           je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
59 @@ -160,41 +165,48 @@
60           }
61        }
62     }
63 -   return true;
64 +   unlock_last_jobs_list();
65 +   return ok;
66  }
67  
68  uint64_t write_last_jobs_list(int fd, uint64_t addr)
69  {
70     struct s_last_job *je;
71     uint32_t num;
72 +   ssize_t stat;
73  
74     Dmsg1(100, "write_last_jobs seek to %d\n", (int)addr);
75     if (lseek(fd, (off_t)addr, SEEK_SET) < 0) {
76        return 0;
77     }
78     if (last_jobs) {
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)) {
83           berrno be;
84           Pmsg1(000, "Error writing num_items: ERR=%s\n", be.bstrerror());
85 -         return 0;
86 +         goto bail_out;
87        }
88        foreach_dlist(je, last_jobs) {
89           if (write(fd, je, sizeof(struct s_last_job)) != sizeof(struct s_last_job)) {
90              berrno be;
91              Pmsg1(000, "Error writing job: ERR=%s\n", be.bstrerror());
92 -            return 0;
93 +            goto bail_out;
94           }
95        }
96 +      unlock_last_jobs_list();
97     }
98     /* Return current address */
99 -   ssize_t stat = lseek(fd, 0, SEEK_CUR);
100 +   stat = lseek(fd, 0, SEEK_CUR);
101     if (stat < 0) {
102        stat = 0;
103     }
104     return stat;
105  
106 +bail_out:
107 +   unlock_last_jobs_list();
108 +   return 0;
109  }
110  
111  void lock_last_jobs_list()
112 @@ -331,6 +343,7 @@
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));
119           if (!last_jobs) {
120 @@ -342,6 +355,7 @@
121              last_jobs->remove(je);
122              free(je);
123           }
124 +         unlock_last_jobs_list();
125        }
126        break;
127     default: