X-Git-Url: http://git.liburcu.org/?p=lttng-ust.git;a=blobdiff_plain;f=libringbuffer%2Fshm.c;h=fb2df13bc11a5a1a43c0b5dc3394930fb8e1bd9a;hp=3bf648d253bd4f00ad8791b34cecb3d75e0c19d2;hb=a9ff648cc;hpb=181c4480c080cb552a6768b2e40849ee04252777 diff --git a/libringbuffer/shm.c b/libringbuffer/shm.c index 3bf648d2..fb2df13b 100644 --- a/libringbuffer/shm.c +++ b/libringbuffer/shm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include /* For mode constants */ #include /* For O_* constants */ #include @@ -29,7 +30,6 @@ #include #include #include -#include #include #include @@ -83,14 +83,69 @@ struct shm_object_table *shm_object_table_create(size_t max_nb_obj) return table; } +static +int create_posix_shm(void) +{ + char tmp_name[NAME_MAX] = "/ust-shm-tmp-XXXXXX"; + int shmfd, ret; + + /* + * Allocate shm, and immediately unlink its shm oject, keeping + * only the file descriptor as a reference to the object. If it + * already exists (caused by short race window during which the + * global object exists in a concurrent shm_open), simply retry. + * 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). + */ + do { + /* + * Using mktemp filename with O_CREAT | O_EXCL open + * flags. + */ + (void) mktemp(tmp_name); + if (tmp_name[0] == '\0') { + PERROR("mktemp"); + goto error_shm_open; + } + shmfd = shm_open(tmp_name, + O_CREAT | O_EXCL | O_RDWR, 0700); + } while (shmfd < 0 && (errno == EEXIST || errno == EACCES)); + if (shmfd < 0) { + PERROR("shm_open"); + goto error_shm_open; + } + ret = shm_unlink(tmp_name); + if (ret < 0 && errno != ENOENT) { + PERROR("shm_unlink"); + goto error_shm_release; + } + return shmfd; + +error_shm_release: + ret = close(shmfd); + if (ret) { + PERROR("close"); + assert(0); + } +error_shm_open: + return -1; +} + +static +int create_shared_file(const char *shm_path) +{ + return open(shm_path, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); +} + static struct shm_object *_shm_object_table_alloc_shm(struct shm_object_table *table, - size_t memory_map_size) + size_t memory_map_size, + const char *shm_path) { 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) @@ -133,37 +188,21 @@ struct shm_object *_shm_object_table_alloc_shm(struct shm_object_table *table, } sigblocked = 1; - /* - * Allocate shm, and immediately unlink its shm oject, keeping - * only the file descriptor as a reference to the object. If it - * already exists (caused by short race window during which the - * global object exists in a concurrent shm_open), simply retry. - * 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). - */ - do { - /* - * Using mktemp filename with O_CREAT | O_EXCL open - * flags. - */ - (void) mktemp(tmp_name); - if (tmp_name[0] == '\0') { - PERROR("mktemp"); - goto error_shm_open; - } - shmfd = shm_open(tmp_name, - O_CREAT | O_EXCL | O_RDWR, 0700); - } while (shmfd < 0 && (errno == EEXIST || errno == EACCES)); - if (shmfd < 0) { - PERROR("shm_open"); - goto error_shm_open; - } - ret = shm_unlink(tmp_name); - if (ret < 0 && errno != ENOENT) { - PERROR("shm_unlink"); - goto error_shm_release; + + if (!shm_path) { + obj->shm_path[0] = '\0'; + shmfd = create_posix_shm(); + } else { + strncpy(obj->shm_path, shm_path, + sizeof(obj->shm_path)); + obj->shm_path[sizeof(obj->shm_path) - 1] = '\0'; + + /* Path should already exist, but could fail. */ + shmfd = create_shared_file(shm_path); } + if (shmfd < 0) + goto error_shm_open; + sigblocked = 0; ret = pthread_sigmask(SIG_SETMASK, &orig_sigs, NULL); if (ret == -1) { @@ -199,7 +238,6 @@ struct shm_object *_shm_object_table_alloc_shm(struct shm_object_table *table, error_mmap: error_ftruncate: -error_shm_release: error_zero_file: error_sigmask_release: ret = close(shmfd); @@ -207,6 +245,12 @@ error_sigmask_release: PERROR("close"); assert(0); } + if (shm_path) { + ret = unlink(shm_path); + if (ret) { + PERROR("ret"); + } + } error_shm_open: if (sigblocked) { ret = pthread_sigmask(SIG_SETMASK, &orig_sigs, NULL); @@ -291,11 +335,13 @@ alloc_error: struct shm_object *shm_object_table_alloc(struct shm_object_table *table, size_t memory_map_size, - enum shm_object_type type) + enum shm_object_type type, + const char *shm_path) { switch (type) { case SHM_OBJECT_SHM: - return _shm_object_table_alloc_shm(table, memory_map_size); + return _shm_object_table_alloc_shm(table, memory_map_size, + shm_path); case SHM_OBJECT_MEM: return _shm_object_table_alloc_mem(table, memory_map_size); default: @@ -416,6 +462,12 @@ void shmp_object_destroy(struct shm_object *obj) PERROR("close"); assert(0); } + if (obj->shm_path[0]) { + ret = unlink(obj->shm_path); + if (ret) { + PERROR("ret"); + } + } for (i = 0; i < 2; i++) { if (obj->wait_fd[i] < 0) continue;