Bug Summary

File:/home/sdobbs/work/clang/halld_recon/src/libraries/DAQ/async_filebuf.cc
Warning:line 86, column 7
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -main-file-name async_filebuf.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0 -D HAVE_EVIO -D HAVE_TMVA=1 -I .Linux_CentOS7.7-x86_64-gcc4.8.5/libraries/DAQ -I libraries/DAQ -I . -I libraries -I libraries/include -I /w/halld-scifs17exp/home/sdobbs/clang/halld_recon/Linux_CentOS7.7-x86_64-gcc4.8.5/include -I libraries -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/evio/evio-4.4.6/Linux-x86_64/include -I /w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/root/root-6.08.06/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/backward -internal-isystem /usr/local/include -internal-isystem /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /home/sdobbs/work/clang/halld_recon/src -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-01-21-110224-160369-1 -x c++ libraries/DAQ/async_filebuf.cc

libraries/DAQ/async_filebuf.cc

1//
2// File: async_filebuf.cc
3// Created: Wed May 1 09:22:00 EST 2019
4// Creator: richard.t.jones at uconn.edu
5//
6// Require: --std=c++11 -pthread
7//
8
9// This code does not compile on Mac OS X using
10// Xcode 10.1 = Apple LLVM version 10.0.0 (clang-1000.10.44.4)
11// 6/3/2019 DL
12#ifndef __APPLE__
13
14#include <string>
15#include <string.h>
16#include <stdexcept>
17
18#include <async_filebuf.h>
19
20async_filebuf::async_filebuf(int segsize, int segcount, int lookback)
21 : segment_size(segsize),
22 segment_count(segcount),
23 segment_lookback(lookback),
24 readloop_active(0)
25{
26#if VERBOSE_ASYNC_FILEBUF
27 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::async_filebuf(" << segsize << "," << segcount << "," << lookback << ")" << std::endl;
28#endif
29 if (segment_count < segment_lookback + 2) {
30 std::string errmsg("async_filebuf error - insufficient"
31 " segment count for look-back.");
32 std::cerr << errmsg << std::endl;
33 throw std::range_error(errmsg);
34 }
35 int bufsize = segment_size * segment_count;
36 buffer = new char[bufsize];
37 setbuf(buffer, bufsize);
38}
39
40async_filebuf::~async_filebuf()
41{
42#if VERBOSE_ASYNC_FILEBUF
43 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::~async_filebuf()" << std::endl;
44#endif
45 if (is_open())
1
Assuming the condition is true
2
Taking true branch
46 close();
3
Calling 'async_filebuf::close'
47 delete [] buffer;
48}
49
50int async_filebuf::readloop_initiate()
51{
52#if VERBOSE_ASYNC_FILEBUF
53 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::readloop_initiate()" << std::endl;
54#endif
55 if (readloop_active)
56 return -1;
57 segment_count = 0;
58 for (char *p = buffer_start; p < buffer_end; p += segment_size) {
59 segment_cond.push_back(sEmpty);
60 segment_pos.push_back(0);
61 segment_len.push_back(0);
62 ++segment_count;
63 }
64 segment_backstop = 0;
65 readloop_active = 1;
66 readloop_thread = new std::thread(&async_filebuf::readloop, this);
67 buffer_eback = buffer_end;
68 buffer_gptr = buffer_end;
69 buffer_egptr = buffer_end;
70 return 0;
71}
72
73int async_filebuf::readloop_terminate()
74{
75#if VERBOSE_ASYNC_FILEBUF
76 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::readloop_terminate()" << std::endl;
77#endif
78 //std::cout << "bang!!!" << std::endl;
79 if (readloop_active
6.1
Field 'readloop_active' is not equal to 0
6.1
Field 'readloop_active' is not equal to 0
) {
7
Taking true branch
80 std::streampos pos = getpos();
8
Calling 'async_filebuf::getpos'
17
Returning from 'async_filebuf::getpos'
81 if (readloop_thread) {
18
Assuming field 'readloop_thread' is null
19
Taking false branch
82 std::unique_lock<std::mutex> lk(readloop_lock);
83 readloop_active = 0;
84 readloop_wake.notify_one();
85 }
86 readloop_thread->join();
20
Called C++ object pointer is null
87 delete readloop_thread;
88 readloop_thread = 0;
89 std::filebuf::seekpos(pos, std::ios::in);
90 buffer_eback = buffer_end;
91 buffer_gptr = buffer_end;
92 buffer_egptr = buffer_end;
93 segment_cond.clear();
94 segment_pos.clear();
95 segment_len.clear();
96 }
97 return 0;
98}
99
100int async_filebuf::readloop()
101{
102#if VERBOSE_ASYNC_FILEBUF
103 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::readloop()" << std::endl;
104#endif
105 int seg = 0;
106 while (readloop_active) {
107 std::unique_lock<std::mutex> lk(readloop_lock);
108 while (readloop_active && segment_cond[seg] != sEmpty) {
109 readloop_wake.wait(lk);
110 }
111 if (! readloop_active)
112 break;
113 segment_cond[seg] = sFilling;
114 lk.unlock();
115 char *sbase = buffer_start + seg * segment_size;
116 segment_pos[seg] = this->std::filebuf::seekoff(0, std::ios::cur, std::ios::in);
117 std::streamsize nreq = buffer_end - sbase;
118 nreq = (nreq > segment_size)? segment_size : nreq;
119 segment_len[seg] = std::filebuf::xsgetn(sbase, nreq);
120 lk.lock();
121 segment_cond[seg] = sFull;
122 readloop_woke.notify_one();
123 seg = (seg + 1) % segment_count;
124 }
125 return 0;
126}
127
128int async_filebuf::underflow()
129{
130#if VERBOSE_ASYNC_FILEBUF
131 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::underflow()" << std::endl;
132#endif
133 if (!readloop_active) {
134 if (segment_lookback > 0)
135 readloop_initiate();
136 else
137 return std::filebuf::underflow();
138 }
139
140 int seg = segment() % segment_count;
141 if (segoff() > 0)
142 seg = (seg + 1) % segment_count;
143 std::unique_lock<std::mutex> lk(readloop_lock);
144 while (segment_cond[seg] != sFull) {
145 readloop_woke.wait(lk);
146 }
147 segment_cond[seg] = sEmptying;
148 if ((segment_backstop + segment_lookback + 1) % segment_count == seg) {
149 segment_cond[segment_backstop] = sEmpty;
150 readloop_wake.notify_one();
151 segment_backstop = (segment_backstop + 1) % segment_count;
152 }
153 buffer_eback = buffer_start + seg * segment_size;
154 buffer_egptr = buffer_eback + segment_len[seg];
155 buffer_gptr = buffer_eback;
156 if (segment_len[seg] == 0)
157 return EOF(-1);
158 return (unsigned char)*buffer_gptr;
159}
160
161std::streampos async_filebuf::seekoff(std::streamoff off, std::ios::seekdir way,
162 std::ios::openmode which)
163{
164#if VERBOSE_ASYNC_FILEBUF
165 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::seekoff(" << off << "," << way << "," << which << ")" << std::endl;
166#endif
167 if (readloop_active && segment_lookback > 0) {
168 if (way == std::ios::beg)
169 return seekpos(off, which);
170 else if (way == std::ios::cur)
171 return seekpos(getpos() + off, which);
172 else
173 readloop_terminate();
174 }
175 return this->std::filebuf::seekoff(off, way, which);
176}
177
178std::streampos async_filebuf::seekpos(std::streampos pos, std::ios::openmode which)
179{
180#if VERBOSE_ASYNC_FILEBUF
181 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::seekpos(" << pos << "," << which << ")" << std::endl;
182#endif
183 if (! readloop_active || segment_lookback == 0) {
184 return this->std::filebuf::seekpos(pos, which);
185 }
186 if (pos < std::streampos(0))
187 pos = std::streampos(0);
188 std::streampos curpos = getpos();
189 if (abs(pos - curpos) > segment_lookback * segment_size) {
190 if (readloop_active)
191 readloop_terminate();
192 return this->std::filebuf::seekpos(pos, which);
193 }
194
195 int seg = segment();
196 while (pos < segment_pos[seg]) {
197 segment_cond[seg] = sFull;
198 int prevseg = (seg == 0)? segment_count-1 : seg-1;
199 if (segment_cond[prevseg] != sEmptying) {
200 if (readloop_active)
201 readloop_terminate();
202 return this->std::filebuf::seekpos(pos, which);
203 }
204 seg = prevseg;
205 }
206 while (pos >= segment_pos[seg] + segment_len[seg]) {
207 buffer_gptr = buffer_egptr;
208 if (underflow() == EOF(-1))
209 return std::streampos(std::streamoff(-1));
210 seg = (seg + 1) % segment_count;
211 }
212 int off = pos - segment_pos[seg];
213 buffer_eback = buffer_start + seg * segment_size;
214 buffer_gptr = buffer_eback + off;
215 buffer_egptr = buffer_eback + segment_len[seg];
216 return pos;
217}
218
219std::streamsize async_filebuf::xsgetn(char* s, std::streamsize n)
220{
221#if VERBOSE_ASYNC_FILEBUF
222 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::xsgetn(s," << n << ")" << std::endl;
223#endif
224 if (segment_lookback == 0) {
225 return std::filebuf::xsgetn(s,n);
226 }
227
228 std::streamsize nleft=n;
229 while (nleft > 0) {
230 int nbuf = buffer_egptr - buffer_gptr;
231 if (nbuf > 0) {
232 nbuf = (nbuf < nleft)? nbuf : nleft;
233 memcpy(s, buffer_gptr, nbuf);
234#if VERBOSE_ASYNC_FILEBUF
235 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "memcpy(d, s, " << nbuf << ")" << std::endl;
236#endif
237#if SHADOW_DEBUG
238 shadow_ifs.seekg(getpos());
239 char *shadowbuf = new char[nbuf];
240 if (shadow_ifs.read(shadowbuf, nbuf) && shadow_ifs.gcount() == nbuf) {
241 for (int i=0; i<nbuf; ++i) {
242 if (shadowbuf[i] != buffer_gptr[i]) {
243 std::cerr << "Error in async_filebuf::xsgetn - "
244 "data read from buffer does not match "
245 "what reading directly from the file "
246 "gives at the same offset! Cannot continue."
247 << std::endl;
248 exit(6);
249 }
250 }
251 }
252 else {
253 std::cerr << "Error in async_filebuf::xsgetn - "
254 "error reading from the shadow ifstream input. "
255 "Cannot continue."
256 << std::endl;
257 exit(6);
258 }
259 delete [] shadowbuf;
260#endif
261 s += nbuf;
262 buffer_gptr += nbuf;
263 nleft -= nbuf;
264 }
265 else if (underflow() == EOF(-1)) {
266 break;
267 }
268 }
269 return n - nleft;
270}
271
272#else // __APPLE__
273int async_filebuff_disable_for_mac_osx = 0; // symbol so compiled object isn't empty
274#endif // __APPLE__
275

libraries/DAQ/async_filebuf.h

1//
2// File: async_filebuf.h
3// Created: Wed May 1 09:22:00 EST 2019
4// Creator: richard.t.jones at uconn.edu
5//
6
7#ifndef _ASYNC_FILEBUF_
8#define _ASYNC_FILEBUF_
9
10#include <fstream>
11#include <iostream>
12#include <cstdio>
13#include <vector>
14#include <thread>
15#include <mutex>
16#include <condition_variable>
17
18//#define VERBOSE_ASYNC_FILEBUF 1
19//#define SHADOW_DEBUG 1
20
21#define THIS_ASYNCFB"(" << (void*)this << ")" "(" << (void*)this << ")"
22
23class async_filebuf : public std::filebuf {
24
25 public:
26 async_filebuf(int segsize=1000000, int segcount=3, int lookback=1);
27 virtual ~async_filebuf();
28
29 async_filebuf* open(const std::string fname, std::ios::openmode mode) {
30#if VERBOSE_ASYNC_FILEBUF
31 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::open(" << fname << "," << mode << ")" << std::endl;
32#endif
33 std::filebuf::open(fname, mode);
34#if SHADOW_DEBUG
35 shadow_ifs.open(fname, mode);
36#endif
37 return this;
38 }
39
40 async_filebuf* close() {
41#if VERBOSE_ASYNC_FILEBUF
42 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::close()" << std::endl;
43#endif
44 if (readloop_active)
4
Assuming field 'readloop_active' is not equal to 0
5
Taking true branch
45 readloop_terminate();
6
Calling 'async_filebuf::readloop_terminate'
46 std::filebuf::close();
47#if SHADOW_DEBUG
48 shadow_ifs.close();
49#endif
50 return this;
51 }
52
53 std::streamsize in_avail() {
54#if VERBOSE_ASYNC_FILEBUF
55 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::in_avail()" << std::endl;
56#endif
57 if (readloop_active)
58 return buffer_egptr - buffer_gptr;
59 return std::filebuf::in_avail();
60 }
61
62 int snextc() {
63#if VERBOSE_ASYNC_FILEBUF
64 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::snextc()" << std::endl;
65#endif
66 if (readloop_active) {
67 if (buffer_gptr < buffer_egptr)
68 return (unsigned char)*(++buffer_gptr);
69 if (underflow() == EOF(-1))
70 return EOF(-1);
71 return snextc();
72 }
73 return std::filebuf::snextc();
74 }
75
76 int sbumpc() {
77 if (readloop_active) {
78 if (buffer_gptr < buffer_egptr)
79 return (unsigned char)*(buffer_gptr++);
80 if (underflow() == EOF(-1))
81 return EOF(-1);
82 return sbumpc();
83 }
84 return std::filebuf::sbumpc();
85 }
86
87 int sgetc() {
88 if (readloop_active) {
89 if (buffer_gptr == buffer_egptr)
90 return underflow();
91 else
92 return (unsigned char)*buffer_gptr;
93 }
94 return std::filebuf::sgetc();
95 }
96
97 int sputbackc(int c) {
98 if (readloop_active) {
99 int seg = (buffer_gptr - buffer_start) / segment_size;
100 char *eback = buffer_start + seg * segment_size;
101 if (buffer_gptr > eback || c == (unsigned char)buffer_gptr[-1])
102 return (unsigned char)*(--buffer_gptr);
103 else
104 return pbackfail();
105 }
106 return std::filebuf::sputbackc(c);
107 }
108
109 int sungetc() {
110 if (readloop_active) {
111 int seg = (buffer_gptr - buffer_start) / segment_size;
112 char *eback = buffer_start + seg * segment_size;
113 if (buffer_gptr > eback)
114 return (unsigned char)*(--buffer_gptr);
115 else
116 return pbackfail();
117 }
118 return std::filebuf::sungetc();
119 }
120
121 protected:
122 int pbackfail(char c=EOF(-1)) {
123 if (readloop_active)
124 return EOF(-1);
125 return std::filebuf::pbackfail(c);
126 }
127
128 virtual std::streambuf* setbuf(char* s, std::streamsize n) {
129#if VERBOSE_ASYNC_FILEBUF
130 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::setbuf(s," << n << ")" << std::endl;
131#endif
132 if (! readloop_active) {
133 buffer_start = s;
134 buffer_end = s + n;
135 buffer_eback = buffer_end;
136 buffer_gptr = buffer_end;
137 buffer_egptr = buffer_end;
138 }
139 return this;
140 }
141
142 virtual std::streamsize showmanyc() {
143 if (readloop_active) {
144 if (buffer_gptr == buffer_egptr)
145 underflow();
146 return buffer_egptr - buffer_gptr;
147 }
148 return std::filebuf::showmanyc();
149 }
150
151 virtual int uflow() {
152#if VERBOSE_ASYNC_FILEBUF
153 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::uflow()" << std::endl;
154#endif
155 if (readloop_active) {
156 if (underflow() == EOF(-1))
157 return EOF(-1);
158 return (unsigned char)*buffer_gptr++;
159 }
160 return std::filebuf::uflow();
161 }
162
163 virtual int underflow();
164
165 virtual std::streamsize xsgetn(char* s, std::streamsize n);
166
167 virtual std::streampos seekoff(std::streamoff off, std::ios::seekdir way,
168 std::ios::openmode which);
169
170 virtual std::streampos seekpos(std::streampos pos, std::ios::openmode which);
171
172 protected:
173 char *buffer;
174 char *buffer_start;
175 char *buffer_end;
176 char *buffer_eback;
177 char *buffer_gptr;
178 char *buffer_egptr;
179
180 enum segment_state {sFull, sEmptying, sEmpty, sFilling};
181 std::vector<segment_state> segment_cond;
182 std::vector<std::streampos> segment_pos;
183 std::vector<std::streamsize> segment_len;
184 int segment_size;
185 int segment_count;
186 int segment_lookback;
187 int segment_backstop;
188 int readloop_active;
189 std::mutex readloop_lock;
190 std::condition_variable readloop_wake;
191 std::condition_variable readloop_woke;
192 std::thread *readloop_thread;
193
194#if SHADOW_DEBUG
195 std::ifstream shadow_ifs;
196#endif
197
198 protected:
199 int readloop_initiate();
200 int readloop_terminate();
201 int readloop();
202
203 int segment() { return (buffer_gptr - buffer_start) / segment_size; }
204 int segoff() { return (buffer_gptr - buffer_start) % segment_size; }
205
206 std::streampos getpos() {
207 if (! readloop_active
8.1
Field 'readloop_active' is not equal to 0
8.1
Field 'readloop_active' is not equal to 0
)
9
Taking false branch
208 return this->std::filebuf::seekoff(0, std::ios::cur, std::ios::in);
209 else if (buffer_gptr == buffer_egptr) {
10
Assuming field 'buffer_gptr' is equal to field 'buffer_egptr'
11
Taking true branch
210 if (segment_len[segment()] > 0)
12
Assuming the condition is false
13
Taking false branch
211 underflow();
212 if (buffer_gptr == buffer_egptr)
14
Assuming field 'buffer_gptr' is equal to field 'buffer_egptr'
15
Taking true branch
213 return this->std::filebuf::seekoff(0, std::ios::cur, std::ios::in);
16
Value assigned to field 'readloop_thread'
214 }
215 std::streampos pos = segment_pos[segment()] + std::streamsize(segoff());
216#if VERBOSE_ASYNC_FILEBUF
217 std::cout << THIS_ASYNCFB"(" << (void*)this << ")" << "async_filebuf::getpos() returns " << pos << " in segment " << segment() << std::endl;
218#endif
219 return pos;
220 }
221};
222
223#endif