root/jlog_io.c

Revision 042eed459bc7cdb07645334cbce5ff04f2696d3c, 6.7 kB (checked in by James Erickson <je@norsecorp.com>, 3 weeks ago)

memory leak in jlog_file_close() under FreeBSD

Under linux this doesn't cause a leak because pthread_mutex_t is not malloc'd during init. On FreeBSD it is so destroy must be called.

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2005-2008, Message Systems, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *    * Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *    * Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials provided
14  *      with the distribution.
15  *    * Neither the name Message Systems, Inc. nor the names
16  *      of its contributors may be used to endorse or promote products
17  *      derived from this software without specific prior written
18  *      permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 /*
34  * We want the single unix spec, so this define is needed on
35  * the identity crisis that is Linux. pread()/pwrite()
36  */
37 #define _XOPEN_SOURCE 500
38
39 #include "jlog_config.h"
40 #include "jlog_hash.h"
41 #include "jlog_io.h"
42 #include <assert.h>
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <pthread.h>
46 #include <sys/mman.h>
47 #include <sys/stat.h>
48 #include <unistd.h>
49
50 static pthread_mutex_t jlog_files_lock = PTHREAD_MUTEX_INITIALIZER;
51 static jlog_hash_table jlog_files = JLOG_HASH_EMPTY;
52
53 typedef struct {
54   dev_t st_dev;
55   ino_t st_ino;
56 } jlog_file_id;
57
58 struct _jlog_file {
59   jlog_file_id id;
60   int fd;
61   int refcnt;
62   int locked;
63   pthread_mutex_t lock;
64 };
65
66 jlog_file *jlog_file_open(const char *path, int flags, int mode)
67 {
68   struct stat sb;
69   jlog_file_id id;
70   jlog_file *f = NULL;
71   union {
72     jlog_file *f;
73     void *vptr;
74   } pun;
75   int fd, realflags = O_RDWR;
76
77   if (flags & O_CREAT) realflags |= O_CREAT;
78   if (flags & O_EXCL) realflags |= O_EXCL;
79
80   if (pthread_mutex_lock(&jlog_files_lock) != 0) return NULL;
81
82   if (stat(path, &sb) == 0) {
83     if (!S_ISREG(sb.st_mode)) goto out;
84     memset(&id, 0, sizeof(id));
85     id.st_dev = sb.st_dev;
86     id.st_ino = sb.st_ino;
87     if (jlog_hash_retrieve(&jlog_files, (void *)&id, sizeof(jlog_file_id),
88                            &pun.vptr))
89     {
90       if (!(flags & O_EXCL)) {
91         f = pun.f;
92         f->refcnt++;
93       }
94       goto out;
95     }
96   }
97
98   if ((fd = open(path, realflags, mode)) == -1) goto out;
99   if (fstat(fd, &sb) != 0) {
100     while (close(fd) == -1 && errno == EINTR) ;
101     goto out;
102   }
103   id.st_dev = sb.st_dev;
104   id.st_ino = sb.st_ino;
105   if (!(f = malloc(sizeof(jlog_file)))) {
106     while (close(fd) == -1 && errno == EINTR) ;
107     goto out;
108   }
109   memset(f, 0, sizeof(jlog_file));
110   f->id = id;
111   f->fd = fd;
112   f->refcnt = 1;
113   f->locked = 0;
114   pthread_mutex_init(&(f->lock), NULL);
115   if (!jlog_hash_store(&jlog_files, (void *)&f->id, sizeof(jlog_file_id), f)) {
116     while (close(f->fd) == -1 && errno == EINTR) ;
117     free(f);
118     f = NULL;
119   }
120 out:
121   pthread_mutex_unlock(&jlog_files_lock);
122   return f;
123 }
124
125 int jlog_file_close(jlog_file *f)
126 {
127   if (pthread_mutex_lock(&jlog_files_lock) != 0) return 0;
128   if (--f->refcnt == 0) {
129     assert(jlog_hash_delete(&jlog_files, (void *)&f->id, sizeof(jlog_file_id),
130                             NULL, NULL));
131     while (close(f->fd) == -1 && errno == EINTR) ;
132     pthread_mutex_destroy(&(f->lock));
133     free(f);
134   }
135   pthread_mutex_unlock(&jlog_files_lock); 
136   return 1;
137 }
138
139 int jlog_file_lock(jlog_file *f)
140 {
141   struct flock fl;
142   int frv;
143
144   memset(&fl, 0, sizeof(fl));
145   fl.l_type = F_WRLCK;
146   fl.l_whence = SEEK_SET;
147   fl.l_start = 0;
148   fl.l_len = 0;
149
150   if (pthread_mutex_lock(&(f->lock)) != 0) return 0;
151   while ((frv = fcntl(f->fd, F_SETLKW, &fl)) == -1 && (errno == EINTR || errno == EAGAIN)) ;
152   if (frv != 0) {
153     int save = errno;
154     pthread_mutex_unlock(&(f->lock));
155     errno = save;
156     return 0;
157   }
158   f->locked = 1;
159   return 1;
160 }
161
162 int jlog_file_unlock(jlog_file *f)
163 {
164   struct flock fl;
165   int frv;
166
167   if (!f->locked) return 0;
168
169   memset(&fl, 0, sizeof(fl));
170   fl.l_type = F_UNLCK;
171   fl.l_whence = SEEK_SET;
172   fl.l_start = 0;
173   fl.l_len = 0;
174
175   while ((frv = fcntl(f->fd, F_SETLKW, &fl)) == -1 && (errno == EINTR || errno == EAGAIN)) ;
176   if (frv != 0) return 0;
177   f->locked = 0;
178   pthread_mutex_unlock(&(f->lock));
179   return 1;
180 }
181
182 int jlog_file_pread(jlog_file *f, void *buf, size_t nbyte, off_t offset)
183 {
184   while (nbyte > 0) {
185     ssize_t rv = pread(f->fd, buf, nbyte, offset);
186     if (rv == -1 && errno == EINTR) continue;
187     if (rv <= 0) return 0;
188     nbyte -= rv;
189     offset += rv;
190   }
191   return 1;
192 }
193
194 int jlog_file_pwrite(jlog_file *f, const void *buf, size_t nbyte, off_t offset)
195 {
196   while (nbyte > 0) {
197     ssize_t rv = pwrite(f->fd, buf, nbyte, offset);
198     if (rv == -1 && errno == EINTR) continue;
199     if (rv <= 0) return 0;
200     nbyte -= rv;
201     offset += rv;
202   }
203   return 1;
204 }
205
206 int jlog_file_sync(jlog_file *f)
207 {
208   int rv;
209
210 #ifdef HAVE_FDATASYNC
211   while((rv = fdatasync(f->fd)) == -1 && errno == EINTR) ;
212 #else
213   while((rv = fsync(f->fd)) == -1 && errno == EINTR) ;
214 #endif
215   if (rv == 0) return 1;
216   return 0;
217 }
218
219 int jlog_file_map_rdwr(jlog_file *f, void **base, size_t *len)
220 {
221   struct stat sb;
222   void *my_map;
223   int flags = 0;
224
225 #ifdef MAP_SHARED
226   flags = MAP_SHARED;
227 #endif
228   if (fstat(f->fd, &sb) != 0) return 0;
229   my_map = mmap(NULL, sb.st_size, PROT_READ|PROT_WRITE, flags, f->fd, 0);
230   if (my_map == MAP_FAILED) return 0;
231   *base = my_map;
232   *len = sb.st_size;
233   return 1;
234 }
235
236 int jlog_file_map_read(jlog_file *f, void **base, size_t *len)
237 {
238   struct stat sb;
239   void *my_map;
240   int flags = 0;
241
242 #ifdef MAP_SHARED
243   flags = MAP_SHARED;
244 #endif
245   if (fstat(f->fd, &sb) != 0) return 0;
246   my_map = mmap(NULL, sb.st_size, PROT_READ, flags, f->fd, 0);
247   if (my_map == MAP_FAILED) return 0;
248   *base = my_map;
249   *len = sb.st_size;
250   return 1;
251 }
252
253 off_t jlog_file_size(jlog_file *f)
254 {
255   struct stat sb;
256   int rv;
257   while ((rv = fstat(f->fd, &sb)) == -1 && errno == EINTR) ;
258   if (rv != 0) return -1;
259   return sb.st_size;
260 }
261
262 int jlog_file_truncate(jlog_file *f, off_t len)
263 {
264   int rv;
265   while ((rv = ftruncate(f->fd, len)) == -1 && errno == EINTR) ;
266   if (rv == 0) return 1;
267   return 0;
268 }
269
270 /* vim:se ts=2 sw=2 et: */
Note: See TracBrowser for help on using the browser.