X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=libringbuffer%2Fshm.c;h=79977017904308c4f5c05046f176caa7e07fb612;hb=refs%2Fheads%2Fstable-2.0;hp=4afb0c6e25b57f0083d1feb4532b54cbb2b612ec;hpb=96e80018cb6ef2098193bd4d8fe724df29f2faf0;p=lttng-ust.git diff --git a/libringbuffer/shm.c b/libringbuffer/shm.c index 4afb0c6e..79977017 100644 --- a/libringbuffer/shm.c +++ b/libringbuffer/shm.c @@ -1,9 +1,21 @@ /* * libringbuffer/shm.c * - * Copyright 2011 (c) - Mathieu Desnoyers + * Copyright (C) 2005-2012 Mathieu Desnoyers * - * Dual LGPL v2.1/GPL v2 license. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; only + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "shm.h" @@ -19,6 +31,45 @@ #include #include #include +#include + +/* + * Ensure we have the required amount of space available by writing 0 + * into the entire buffer. Not doing so can trigger SIGBUS when going + * beyond the available shm space. + */ +static +int zero_file(int fd, size_t len) +{ + ssize_t retlen; + size_t written = 0; + char *zeropage; + long pagelen; + int ret; + + pagelen = sysconf(_SC_PAGESIZE); + if (pagelen < 0) + return (int) pagelen; + zeropage = calloc(pagelen, 1); + if (!zeropage) + return -ENOMEM; + + while (len > written) { + do { + retlen = write(fd, zeropage, + min_t(size_t, pagelen, len - written)); + } while (retlen == -1UL && errno == EINTR); + if (retlen < 0) { + ret = (int) retlen; + goto error; + } + written += retlen; + } + ret = 0; +error: + free(zeropage); + return ret; +} struct shm_object_table *shm_object_table_create(size_t max_nb_obj) { @@ -116,6 +167,11 @@ struct shm_object *shm_object_table_append(struct shm_object_table *table, PERROR("pthread_sigmask"); goto error_sigmask_release; } + ret = zero_file(shmfd, memory_map_size); + if (ret) { + PERROR("zero_file"); + goto error_zero_file; + } ret = ftruncate(shmfd, memory_map_size); if (ret) { PERROR("ftruncate"); @@ -140,6 +196,7 @@ struct shm_object *shm_object_table_append(struct shm_object_table *table, error_mmap: error_ftruncate: error_shm_release: +error_zero_file: error_sigmask_release: ret = close(shmfd); if (ret) {