diff options
author | joq <joq@0c269be4-1314-0410-8aa9-9f06e86f4224> | 2004-12-25 18:39:44 +0000 |
---|---|---|
committer | joq <joq@0c269be4-1314-0410-8aa9-9f06e86f4224> | 2004-12-25 18:39:44 +0000 |
commit | 5246f2a1045a452bbd9881fea01b7ccfbf6994de (patch) | |
tree | 9de9db4e74d1453c4a27c8aee189b38e0d0c6033 /libjack/shm.c | |
parent | acf0bcecc170b5be057d0eddca1975807e7945c6 (diff) | |
download | jack1-5246f2a1045a452bbd9881fea01b7ccfbf6994de.tar.gz |
[0.99.39] multiserver POSIX shm fixes
git-svn-id: svn+ssh://jackaudio.org/trunk/jack@852 0c269be4-1314-0410-8aa9-9f06e86f4224
Diffstat (limited to 'libjack/shm.c')
-rw-r--r-- | libjack/shm.c | 103 |
1 files changed, 78 insertions, 25 deletions
diff --git a/libjack/shm.c b/libjack/shm.c index 6f7a611..a2e6c54 100644 --- a/libjack/shm.c +++ b/libjack/shm.c @@ -74,16 +74,17 @@ static void jack_remove_shm (jack_shm_id_t *id); * cleanup is also done when a new instance of that server starts. */ -/* global data for the SHM interfaces */ -static jack_shm_id_t registry_id; /* SHM id for the registry */ +/* per-process global data for the SHM interfaces */ +static jack_shm_id_t registry_id; /* SHM id for the registry */ static jack_shm_info_t registry_info = { /* SHM info for the registry */ .index = JACK_SHM_NULL_INDEX, .attached_at = MAP_FAILED }; /* pointers to registry header and array */ -static jack_shm_header_t* jack_shm_header = NULL; -static jack_shm_registry_t* jack_shm_registry = NULL; +static jack_shm_header_t *jack_shm_header = NULL; +static jack_shm_registry_t *jack_shm_registry = NULL; +static char jack_shm_server_prefix[JACK_SERVER_NAME_SIZE] = ""; /* jack_shm_lock_registry() serializes updates to the shared memory * segment JACK uses to keep track of the SHM segements allocated to @@ -215,6 +216,29 @@ jack_shm_validate_registry () return -1; } +/* set a unique per-user, per-server shm prefix string + * + * According to the POSIX standard: + * + * "The name argument conforms to the construction rules for a + * pathname. If name begins with the slash character, then processes + * calling shm_open() with the same value of name refer to the same + * shared memory object, as long as that name has not been + * removed. If name does not begin with the slash character, the + * effect is implementation-defined. The interpretation of slash + * characters other than the leading slash character in name is + * implementation-defined." + * + * Since the Linux implementation does not allow slashes *within* the + * name, in the interest of portability we use colons instead. + */ +static void +jack_set_server_prefix (const char *server_name) +{ + snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix), + "/jack-%d:%s:", getuid (), server_name); +} + /* gain server addressability to shared memory registration segment * * returns: 0 if successful @@ -269,13 +293,15 @@ jack_server_initialize_shm (void) * returns: 0 if successful */ int -jack_initialize_shm (void) +jack_initialize_shm (const char *server_name) { int rc; if (jack_shm_header) return 0; /* already initialized */ + jack_set_server_prefix (server_name); + jack_shm_lock_registry (); if ((rc = jack_access_registry (®istry_info)) == 0) { if ((rc = jack_shm_validate_registry ()) != 0) { @@ -319,14 +345,23 @@ jack_get_free_shm_info () return si; } +static inline void +jack_release_shm_entry (jack_shm_registry_index_t index) +{ + /* the registry must be locked */ + jack_shm_registry[index].size = 0; + jack_shm_registry[index].allocator = 0; + memset (&jack_shm_registry[index].id, 0, + sizeof (jack_shm_registry[index].id)); +} + void jack_release_shm_info (jack_shm_registry_index_t index) { /* must NOT have the registry locked */ if (jack_shm_registry[index].allocator == getpid()) { jack_shm_lock_registry (); - jack_shm_registry[index].size = 0; - jack_shm_registry[index].allocator = 0; + jack_release_shm_entry (index); jack_shm_unlock_registry (); } } @@ -343,7 +378,8 @@ jack_register_server (const char *server_name) { int i; pid_t my_pid = getpid (); - char *server_directory = jack_server_dir (server_name); + + jack_set_server_prefix (server_name); fprintf (stderr, "JACK compiled with %s SHM support.\n", JACK_SHM_TYPE); @@ -353,12 +389,12 @@ jack_register_server (const char *server_name) jack_shm_lock_registry (); /* See if server_name already registered. Since server names - * are per-user, we register the server directory path name, - * which must be unique. */ + * are per-user, we register the unique server prefix string. + */ for (i = 0; i < MAX_SERVERS; i++) { if (strncmp (jack_shm_header->server[i].name, - server_directory, + jack_shm_server_prefix, JACK_SERVER_NAME_SIZE) != 0) continue; /* no match */ @@ -387,7 +423,7 @@ jack_register_server (const char *server_name) /* claim it */ jack_shm_header->server[i].pid = my_pid; strncpy (jack_shm_header->server[i].name, - server_directory, + jack_shm_server_prefix, JACK_SERVER_NAME_SIZE); jack_shm_unlock_registry (); @@ -406,9 +442,8 @@ jack_unregister_server (const char *server_name /* unused */) for (i = 0; i < MAX_SERVERS; i++) { if (jack_shm_header->server[i].pid == my_pid) { - jack_shm_header->server[i].pid = 0; - memset (jack_shm_header->server[i].name, 0, - JACK_SERVER_NAME_SIZE); + memset (&jack_shm_header->server[i], 0, + sizeof (jack_shm_server_t)); } } @@ -430,7 +465,7 @@ jack_cleanup_shm () jack_shm_registry_t* r; r = &jack_shm_registry[i]; - copy.index = r->index; + memcpy (©, r, sizeof (jack_shm_info_t)); destroy = FALSE; /* ignore unused entries */ @@ -456,15 +491,14 @@ jack_cleanup_shm () } } } - + if (destroy) { int index = copy.index; if ((index >= 0) && (index < MAX_SHM_ID)) { jack_remove_shm (&jack_shm_registry[index].id); - jack_shm_registry[index].size = 0; - jack_shm_registry[index].allocator = 0; + jack_release_shm_entry (index); } r->size = 0; r->allocator = 0; @@ -618,38 +652,55 @@ jack_create_registry (jack_shm_info_t *ri) static void jack_remove_shm (jack_shm_id_t *id) { - shm_unlink (*id); + /* registry may or may not be locked */ + shm_unlink ((char *) id); } void jack_release_shm (jack_shm_info_t* si) { - //printf("client->jack_release_shm \n"); + /* registry may or may not be locked */ if (si->attached_at != MAP_FAILED) { - //printf("client->jack_release_shm 1 \n"); munmap (si->attached_at, jack_shm_registry[si->index].size); } } +/* allocate a POSIX shared memory segment + * + * The shm_name should not have a leading slash, that will be provided + * here along with a prefix making it unique to this server. + */ int jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si) { jack_shm_registry_t* registry; int shm_fd; int rc = -1; + char name[NAME_MAX+1]; + + /* concatenate jack_shm_server_prefix and shm_name to build a + * unique name per user and per server */ + snprintf (name, sizeof (name), "%s%s", + jack_shm_server_prefix, shm_name); + + if (strlen (name) >= sizeof (jack_shm_id_t)) { + jack_error ("shm segment name too long %s", name); + return -1; + } jack_shm_lock_registry (); if ((registry = jack_get_free_shm_info ())) { - if ((shm_fd = shm_open (shm_name, O_RDWR|O_CREAT, 0666)) >= 0) { + if ((shm_fd = shm_open (name, O_RDWR|O_CREAT, 0666)) >= 0) { if (ftruncate (shm_fd, size) >= 0) { close (shm_fd); registry->size = size; + //JOQ: better to use strncpy() here... snprintf (registry->id, sizeof (registry->id), - "%s", shm_name); + "%s", name); registry->allocator = getpid(); si->index = registry->index; si->attached_at = MAP_FAILED; /* not attached */ @@ -663,7 +714,7 @@ jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si) } else { jack_error ("cannot create shm segment %s (%s)", - shm_name, strerror (errno)); + name, strerror (errno)); } } @@ -792,12 +843,14 @@ jack_create_registry (jack_shm_info_t *ri) static void jack_remove_shm (jack_shm_id_t *id) { + /* registry may or may not be locked */ shmctl (*id, IPC_RMID, NULL); } void jack_release_shm (jack_shm_info_t* si) { + /* registry may or may not be locked */ if (si->attached_at != MAP_FAILED) { shmdt (si->attached_at); } |