diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2004-03-30 19:20:08 +0400 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2004-03-30 19:20:08 +0400 |
commit | 5c7b73ed978ba139423813144e4eecccf016c81a (patch) | |
tree | a1138ea59cfdc67fd737da7406aa221b10d72364 | |
parent | 66c8e18830451ee6ffc231586c65fbf2c06535b2 (diff) |
* shm.cc (shmat): If shmid is unknown, call a special variation
of shmget to retrieve the shared memory segment from Cygserver
instead of failing immediately.
* include/cygwin/ipc.h (IPC_KEY_IS_SHMID): New internal flag for
shmget when called from shmat.
-rw-r--r-- | winsup/cygwin/ChangeLog | 8 | ||||
-rw-r--r-- | winsup/cygwin/include/cygwin/ipc.h | 3 | ||||
-rw-r--r-- | winsup/cygwin/shm.cc | 23 |
3 files changed, 31 insertions, 3 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index aa0951ee9..b81057696 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,11 @@ +2004-03-30 Corinna Vinschen <corinna@vinschen.de> + + * shm.cc (shmat): If shmid is unknown, call a special variation + of shmget to retrieve the shared memory segment from Cygserver + instead of failing immediately. + * include/cygwin/ipc.h (IPC_KEY_IS_SHMID): New internal flag for + shmget when called from shmat. + 2004-03-29 Corinna Vinschen <corinna@vinschen.de> * fhandler.h (class fhandler_socket): Add has_been_closed member. diff --git a/winsup/cygwin/include/cygwin/ipc.h b/winsup/cygwin/include/cygwin/ipc.h index 90534c29d..d0f5beaa1 100644 --- a/winsup/cygwin/include/cygwin/ipc.h +++ b/winsup/cygwin/include/cygwin/ipc.h @@ -32,6 +32,9 @@ struct ipc_perm /* Mode bits: */ +#ifdef _KERNEL +#define IPC_KEY_IS_SHMID 0x0100 /* Used in shmget when called from shmat. */ +#endif #define IPC_CREAT 0x0200 /* Create entry if key does not exist. */ #define IPC_EXCL 0x0400 /* Fail if key exists. */ #define IPC_NOWAIT 0x0800 /* Error if request must wait. */ diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc index 7e4be9ebd..4bae7b2d2 100644 --- a/winsup/cygwin/shm.cc +++ b/winsup/cygwin/shm.cc @@ -160,9 +160,26 @@ shmat (int shmid, const void *shmaddr, int shmflg) } if (!ssh_entry) { - /* Invalid shmid */ - set_errno (EINVAL); - return (void *) -1; + /* The shmid is unknown to this process so far. Try to get it from + the server if it exists. Use special internal call to shmget, + which interprets the key as a shmid and only returns a valid + shmid if one exists. Since shmctl inserts a new entry for this + shmid into ssh_list automatically, we just have to go through + that list again. If that still fails, well, bad luck. */ + if (shmid && shmget ((key_t) shmid, 0, IPC_KEY_IS_SHMID) != -1) + { + SLIST_FOREACH (ssh_entry, &ssh_list, ssh_next) + { + if (ssh_entry->shmid == shmid) + break; + } + } + if (!ssh_entry) + { + /* Invalid shmid */ + set_errno (EINVAL); + return (void *) -1; + } } vm_object_t attach_va = NULL; if (shmaddr) |