From 5c7b73ed978ba139423813144e4eecccf016c81a Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 30 Mar 2004 15:20:08 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 8 ++++++++ winsup/cygwin/include/cygwin/ipc.h | 3 +++ 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 + + * 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 * 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) -- 2.43.5