X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=libringbuffer%2Fshm.c;h=c10e58a23cc281fb06128c93d16697efc2d0b019;hb=dda4784f1d19fa0426cbaae0738c054ee4d39cba;hp=563903877f5eb59a62409ce32662a8bd6f7600bd;hpb=a88038977008704e88544601cef0291b138f8387;p=lttng-ust.git diff --git a/libringbuffer/shm.c b/libringbuffer/shm.c index 56390387..c10e58a2 100644 --- a/libringbuffer/shm.c +++ b/libringbuffer/shm.c @@ -13,7 +13,12 @@ #include /* For mode constants */ #include /* For O_* constants */ #include -#include +#include +#include +#include +#include +#include +#include struct shm_object_table *shm_object_table_create(size_t max_nb_obj) { @@ -28,9 +33,11 @@ struct shm_object_table *shm_object_table_create(size_t max_nb_obj) struct shm_object *shm_object_table_append(struct shm_object_table *table, size_t memory_map_size) { - int shmfd, waitfd[2], ret, i; + int shmfd, waitfd[2], ret, i, sigblocked = 0; struct shm_object *obj; char *memory_map; + char tmp_name[NAME_MAX] = "/ust-shm-tmp-XXXXXX"; + sigset_t all_sigs, orig_sigs; if (table->allocated_len >= table->size) return NULL; @@ -59,6 +66,19 @@ struct shm_object *shm_object_table_append(struct shm_object_table *table, /* shm_fd: create shm */ + /* + * Theoretically, we could leak a shm if the application crashes + * between open and unlink. Disable signals on this thread for + * increased safety against this scenario. + */ + sigfillset(&all_sigs); + ret = pthread_sigmask(SIG_BLOCK, &all_sigs, &orig_sigs); + if (ret == -1) { + PERROR("pthread_sigmask"); + goto error_pthread_sigmask; + } + sigblocked = 1; + /* * Allocate shm, and immediately unlink its shm oject, keeping * only the file descriptor as a reference to the object. If it @@ -67,30 +87,35 @@ struct shm_object *shm_object_table_append(struct shm_object_table *table, * We specifically do _not_ use the / at the beginning of the * pathname so that some OS implementations can keep it local to * the process (POSIX leaves this implementation-defined). - * Ignore the shm_unlink errors, because we handle leaks that - * could occur by applications crashing between shm_open and - * shm_unlink by unlinking the shm before every open. Therefore, - * we can only leak one single shm (and only if the application - * crashes between shm_open and the following shm_unlink). */ do { - ret = shm_unlink("ust-shm-tmp"); - if (ret < 0 && errno != ENOENT) { - PERROR("shm_unlink"); - goto error_shm_unlink; + /* + * Using mktemp filename with O_CREAT | O_EXCL open + * flags. + */ + mktemp(tmp_name); + if (tmp_name[0] == '\0') { + PERROR("mktemp"); + goto error_shm_open; } - shmfd = shm_open("ust-shm-tmp", + shmfd = shm_open(tmp_name, O_CREAT | O_EXCL | O_RDWR, 0700); - } while (shmfd < 0 && errno == EEXIST); + } while (shmfd < 0 && (errno == EEXIST || errno == EACCES)); if (shmfd < 0) { PERROR("shm_open"); goto error_shm_open; } - ret = shm_unlink("ust-shm-tmp"); + ret = shm_unlink(tmp_name); if (ret < 0 && errno != ENOENT) { PERROR("shm_unlink"); goto error_shm_release; } + sigblocked = 0; + ret = pthread_sigmask(SIG_SETMASK, &orig_sigs, NULL); + if (ret == -1) { + PERROR("pthread_sigmask"); + goto error_sigmask_release; + } ret = ftruncate(shmfd, memory_map_size); if (ret) { PERROR("ftruncate"); @@ -115,13 +140,20 @@ struct shm_object *shm_object_table_append(struct shm_object_table *table, error_mmap: error_ftruncate: error_shm_release: +error_sigmask_release: ret = close(shmfd); if (ret) { PERROR("close"); assert(0); } -error_shm_unlink: error_shm_open: + if (sigblocked) { + ret = pthread_sigmask(SIG_SETMASK, &orig_sigs, NULL); + if (ret == -1) { + PERROR("pthread_sigmask"); + } + } +error_pthread_sigmask: error_fcntl: for (i = 0; i < 2; i++) { ret = close(waitfd[i]); @@ -135,22 +167,61 @@ error_pipe: } +struct shm_object *shm_object_table_append_shadow(struct shm_object_table *table, + int shm_fd, int wait_fd, size_t memory_map_size) +{ + struct shm_object *obj; + char *memory_map; + + if (table->allocated_len >= table->size) + return NULL; + obj = &table->objects[table->allocated_len]; + + /* wait_fd: set read end of the pipe. */ + obj->wait_fd[0] = wait_fd; + obj->wait_fd[1] = -1; /* write end is unset. */ + obj->shm_fd = shm_fd; + + /* memory_map: mmap */ + memory_map = mmap(NULL, memory_map_size, PROT_READ | PROT_WRITE, + MAP_SHARED, shm_fd, 0); + if (memory_map == MAP_FAILED) { + PERROR("mmap"); + goto error_mmap; + } + obj->memory_map = memory_map; + obj->memory_map_size = memory_map_size; + obj->allocated_len = memory_map_size; + obj->index = table->allocated_len++; + + return obj; + +error_mmap: + return NULL; +} + static void shmp_object_destroy(struct shm_object *obj) { int ret, i; - ret = munmap(obj->memory_map, obj->memory_map_size); - if (ret) { - PERROR("umnmap"); - assert(0); - } - ret = close(obj->shm_fd); - if (ret) { - PERROR("close"); - assert(0); + if (!obj->is_shadow) { + ret = munmap(obj->memory_map, obj->memory_map_size); + if (ret) { + PERROR("umnmap"); + assert(0); + } + } + if (obj->shm_fd >= 0) { + ret = close(obj->shm_fd); + if (ret) { + PERROR("close"); + assert(0); + } } for (i = 0; i < 2; i++) { + if (obj->wait_fd[i] < 0) + continue; ret = close(obj->wait_fd[i]); if (ret) { PERROR("close");