This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

cygipc-1.11 SHM-patch: fork, handling in ipc-daemon


Hello Chuck!

Yes, it's me again!

Sorry for let you that long time without answer, but now
i have some improvements on cygipc 1.11, because the
cygwin-daemon looks not like appearing in next few weeks:

*)
2 fixes in semctl() with cmd SETALL: SUSv2 (thank you for
specifying to use it from opengroup.org, i could not decide
which google-result to use) says that SETALL _sets_ (not add,
fix 1) the 'semval' for _all_ (not just for semnum, fix 2)
semaphores in the set.
It is not explicitly defined (Linux does) that the semnum
parameter is ignored, but what else should be done with it.

*)
Implementation of GETALL in semctl().

*)
Implementation of the pthread_atfork-mechanism for shm to
register the child as attached and incrementing shm_nattch.
Thanks to Robert Collins for the hint in
http://www.cygwin.com/ml/cygwin/2001-11/msg01602.html

*)
When mmap() fails in shmat(), do not attach and return
an error (the errno of mmap, i don't know a better one yet).

*)
Reformatting work_main() in ipc-daemon.c for better
readability to be able to fix at least three problems:

- It is not good to munmap() and close() a file and it's map
  of another process even if the file-no and the start-address
  of the map is known, found during invalidation of the
  attachlist-entry for a dead process.

- This ought to be done when an attached process dies
  without detaching, to keep shm_nattch up to date.
  But this was not done while another process was
  attached before in the list as the dead process was.

- It is not clear what happens in following circumstance:
  1) the first process creates a shm
  2) a second one attaches to it
  3) now the second process dies without detaching
  4) the first process removes the shm with shmctl(IPC_RMID),
     but the ipc-daemon was sleeping and did not remove the
     second attachment-entry early enough to have shm_nattch==0,
     which must be the case in shmctl() to really remove the shm
     by the caller of shmctl(IPC_RMID).

  What IMHO surely not should happen is that a shmid with
  shm_nattch==0 remains with having the destroy-flag set.
  So the ipc-daemon must remove a shm in this state,
  including the tmp-file.

*)
Removing files in /tmp now:
- after destroying a shm, the memmap /tmp/cygipc<id>.
  this was really missing: if an application uses a large shm,
  or many shm's are in use at one time, the diskspace
  should be free'd after shutdown this application.
- after shutdown of ipc-daemon, the MultiFileXXX.
  maybe this would not really be needed, but it looks not
  good if some files are left in /tmp after stopping a daemon.

Hopefully these fixes do not affect postgres to much...

Greets,
  haubi
-- 
Michael Haubenwallner                       SALOMON Automation GmbH
Forschung & Entwicklung                     A-8114 Friesach bei Graz
mailto:michael.haubenwallner@salomon.at     http://www.salomon.at
diff -ru cygipc-1.11/ipc-daemon.c cygipc/ipc-daemon.c
--- cygipc-1.11/ipc-daemon.c	Fri Feb 16 17:15:08 2001
+++ cygipc/ipc-daemon.c	Thu Jan 17 17:20:22 2002
@@ -148,287 +148,398 @@
 	return;
 }
 
+static void destroy_map(const char *pcName,
+		int *pnFd, caddr_t *ppMap, size_t nSize,
+		const char *pcFile)
+{
+	if (ppMap != NULL && *ppMap != (caddr_t)-1) {
+		if (munmap(*ppMap, nSize) < 0) {
+			log_message(stderr, LOG_ERR,
+				"Unable to unmap \"%s\" file: %s",
+				pcName, strerror(errno));
+		}
+		*ppMap = (caddr_t)-1;
+	}
+
+	if (pnFd != NULL && *pnFd >= 0) {
+		if (close(*pnFd) < 0) {
+			log_message(stderr, LOG_ERR,
+				"Unable to close \"%s\" file: %s",
+				pcName, strerror(errno));
+		}
+		*pnFd = -1;
+
+		if (pcFile != NULL) {
+			if (unlink(pcFile) < 0) {
+				log_message(stderr, LOG_ERR,
+					"Unable to remove \"%s\" file: %s",
+					pcName, strerror(errno));
+			}
+		}
+	}
+
+	return;
+}
+
+static int create_map(const char *pcName,
+		int *pnFdRet, caddr_t *ppMapRet, size_t nSize,
+		const char *pcFile)
+{
+	int		iRv;
+	int		nFd = -1;
+	void	*pvBuf = NULL;
+	caddr_t	pMap = (caddr_t)-1;
+
+	do {	/* dummy loop */
+		iRv = -1;
+
+		nFd = open(pcFile, O_CREAT|O_RDWR, 0666 );  /* O_TRUNC ? */
+		if (nFd < 0) {
+			log_message(stderr, LOG_ERR,
+				"Unable to open \"%s\" file: %s",
+				pcName, strerror(errno));
+			break;
+		}
+
+		pvBuf = malloc(nSize);
+		if (pvBuf == NULL) {
+			log_message(stderr, LOG_ERR,
+				"Unable to allocate \"%s\" memory: %s",
+				pcName, strerror(errno));
+			break;
+		}
+
+		memset(pvBuf, 0, nSize) ;
+		if (write(nFd, pvBuf, nSize) != (ssize_t)nSize) {
+			log_message(stderr, LOG_ERR,
+				"Unable to write \"%s\" file: %s",
+				pcName, strerror(errno));
+			break;
+		}
+		close(nFd);
+
+		nFd  = open(pcFile, O_RDWR, 0666);
+		if (nFd < 0) {
+			log_message(stderr, LOG_ERR,
+				"Unable to open \"%s\" file again: %s",
+				pcName, strerror(errno));
+			break;
+		}
+		pMap = mmap(0, nSize, PROT_READ|PROT_WRITE, MAP_SHARED, nFd, 0);
+		if (pMap == (caddr_t)-1) {
+			log_message(stderr, LOG_ERR,
+				"Unable to mmap \"%s\" file: %s",
+				pcName, strerror(errno));
+			break;
+		}
+
+		iRv = 0;
+	} while(0);	/* end dummy loop */
+	
+	if (pvBuf != NULL) {
+		free(pvBuf);
+	}
+
+	if (iRv < 0) {
+		if (nFd >= 0) {
+			close(nFd);
+			nFd = -1;
+		}
+	}
+
+	*pnFdRet = nFd;
+	*ppMapRet = pMap;
+
+	return iRv;
+}
+
 int work_main(void)
 {
-  HANDLE LSemControl ;
-  int LFdSem, LFdShm, LFdMsg ;
-  CYGWIN_IPCNT_SEMSTR *LAdrSem ;
-  CYGWIN_IPCNT_SHMSTR *LAdrShm ;
-  CYGWIN_IPCNT_MSGSTR *LAdrMsg ;
-  SECURITY_ATTRIBUTES sa;
- 
-  HANDLE LHandle ;
-  char LBuff[100] ;
-  int id, Index ;
-  struct semid_ds *sma ;
-  long LPrevious ;
-  int LComptShm = 0 ;
-  int LRet ;
-
-  get_null_sa(&sa);
-  
-  LSemControl = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, CYGWIN_IPCNT_SEMCTL) ;
- 
-  if( LSemControl == NULL )
-  {
-    LSemControl = CreateSemaphore(tight_security ? NULL : &sa, 0, 1, CYGWIN_IPCNT_SEMCTL) ;
-    if( LSemControl == NULL )
-    {
-      log_message(stderr, LOG_ERR, "Unable to create a semaphore");
-    }
-    else
-    {
-      /*********************************************************************/
-      /* Creation des semaphore de gestion des memoires partagees		*/
-      /* Si il existe dans le systeme, On les vire				*/
-      /*********************************************************************/
-      GSemSem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, CYGWIN_IPCNT_SEMSEM) ;
-      if( GSemSem != NULL )
-      {
-        CloseHandle ( GSemSem ) ;
-      }
-   
-      GSemSem = CreateSemaphore(tight_security ? NULL : &sa, 1, 1, CYGWIN_IPCNT_SEMSEM) ;
-   
-      if( GSemSem == NULL )
-      {
-        log_message(stderr, LOG_ERR, "Unable to create \"Shm\" semaphore" ) ;
-        goto endko ;
-      }
-   
-      GSemShm = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, CYGWIN_IPCNT_SEMSHM) ;
-      if( GSemShm != NULL )
-      {
-        CloseHandle ( GSemShm ) ;
-      }
-      GSemShm = CreateSemaphore(tight_security ? NULL : &sa, 1, 1, CYGWIN_IPCNT_SEMSHM) ;
-      if( GSemSem == NULL )
-      {
-        log_message(stderr, LOG_ERR, "Unable to create \"Shm\" semaphore" ) ;
-        goto endko ;
-      }
-      GSemMsg = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, CYGWIN_IPCNT_SEMMSG) ;
-      if( GSemMsg != NULL )
-      {
-        CloseHandle ( GSemMsg ) ;
-      }
-      GSemMsg = CreateSemaphore(tight_security ? NULL : &sa, 1, 1, CYGWIN_IPCNT_SEMMSG) ; ;
-      if( GSemSem == NULL )
-      {
-        log_message(stderr, LOG_ERR, "Unable to create \"Msg\" semaphore" ) ;
-        goto endko ;
-      }
-   
-      /*********************************************************************/
-      /* Creation des memoires partagees					*/
-      /*********************************************************************/
-   
-      /*********************************************************************/
-      /* On commence par le semaphore					*/
-      /*********************************************************************/
-      LFdSem = open(CYGWIN_IPCNT_FILESEM, O_CREAT|O_RDWR, 00666 ) ;  /* O_TRUNC ? */
-      GStrSem = (CYGWIN_IPCNT_SEMSTR *) malloc (sizeof(CYGWIN_IPCNT_SEMSTR)) ;
-      memset (GStrSem, 0x00, sizeof(CYGWIN_IPCNT_SEMSTR)) ;
-      write(LFdSem, GStrSem, sizeof(CYGWIN_IPCNT_SEMSTR)) ;
-      free(GStrSem) ;
-      close(LFdSem) ;
-   
-      LFdSem  = open(CYGWIN_IPCNT_FILESEM, O_RDWR, 00666 ) ;
-      LAdrSem = (CYGWIN_IPCNT_SEMSTR *)
-      		mmap(0, sizeof(CYGWIN_IPCNT_SEMSTR), PROT_READ|PROT_WRITE,
-   		MAP_SHARED, LFdSem, 0) ;
-      sem_init(LAdrSem) ;
-   
-      /*********************************************************************/
-      /* On continue par la memoire partagee				*/
-      /*********************************************************************/
-      LFdShm = open(CYGWIN_IPCNT_FILESHM, O_CREAT|O_RDWR|O_TRUNC, 00666 ) ;
-      GStrShm = (CYGWIN_IPCNT_SHMSTR *) malloc (sizeof(CYGWIN_IPCNT_SHMSTR)) ;
-      memset (GStrShm, 0x00, sizeof(CYGWIN_IPCNT_SHMSTR)) ;
-      write(LFdShm, GStrShm, sizeof(CYGWIN_IPCNT_SHMSTR)) ;
-      free (GStrShm) ;
-      close(LFdShm) ;
-   
-      LFdShm  = open(CYGWIN_IPCNT_FILESHM, O_RDWR, 00666 ) ;
-      LAdrShm = (CYGWIN_IPCNT_SHMSTR *)
-      		mmap(0, sizeof(CYGWIN_IPCNT_SHMSTR), PROT_READ|PROT_WRITE,
-   		MAP_SHARED, LFdShm, 0) ;
-      shm_init(LAdrShm) ;
-   
-      /*********************************************************************/
-      /* On finit par les messages queues					*/
-      /*********************************************************************/
-      LFdMsg = open(CYGWIN_IPCNT_FILEMSG, O_CREAT|O_RDWR|O_TRUNC, 00666 ) ;
-      GStrMsg = (CYGWIN_IPCNT_MSGSTR *) malloc (sizeof(CYGWIN_IPCNT_MSGSTR)) ;
-      memset (GStrMsg, 0x00, sizeof(CYGWIN_IPCNT_MSGSTR)) ;
-      write(LFdMsg, GStrMsg, sizeof(CYGWIN_IPCNT_MSGSTR)) ;
-      free(GStrMsg) ;
-      close(LFdMsg) ;
-   
-      LFdMsg  = open(CYGWIN_IPCNT_FILEMSG, O_RDWR, 00666 ) ;
-      LAdrMsg = (CYGWIN_IPCNT_MSGSTR *)
-      		mmap(0, sizeof(CYGWIN_IPCNT_MSGSTR), PROT_READ|PROT_WRITE,
-   		MAP_SHARED, LFdMsg, 0) ;
-      msg_init(LAdrMsg) ;
-   
-      hStopEvent = CreateEvent(tight_security ? NULL : &sa, TRUE, FALSE, NULL);
-      if (! hStopEvent) {
-        log_message(stderr, LOG_ERR, "failed to create stop event");
-      }
-   
-      if (service) {
-        ss.dwCheckPoint = 0;
-        ss.dwWaitHint = 0;
-        ss.dwCurrentState = SERVICE_RUNNING;
-        SetServiceStatus(ssh, &ss);
-        log_message(stderr, LOG_INFO, "'ipc-daemon' service started"); 
-      }
-   
-   
-      /* log_message(stderr, LOG_INFO, "'ipc-deamon' is now running..." ) ; */
-   
-      /*********************************************************************/
-      /* On boucle afin de recuperer les Handle des objets crees		*/
-      /* par les fonctions IPC						*/
-      /*********************************************************************/
-      while(1)
-      {
-        HANDLE hObjects[2];
-        DWORD ret;
-        usleep(300000) ;
-   
-       /********************************************************************/
-       /* Semaphores							*/
-       /********************************************************************/
-   
-        hObjects[0] = hStopEvent;
-        hObjects[1] = GSemSem;
-        /* The order of the objects matters, since we want the stop-event
-         to take precedence over the GSemSem-semaphore which is almost
-         always signalled. */
-   
-        ret = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE) ;
-        //log_message(stderr, LOG_INFO, "WaitForMultipleObjects ret %ld", ret);
-   
-        switch (ret) {
-        case WAIT_OBJECT_0:
-          /* got the stop-event */
-          goto end;
-   
-        default:
-          log_message(stderr, LOG_ERR, "unexpected return from wait, %ld", ret);
-          goto end;
-   
-        case WAIT_OBJECT_0+1:
-          for (id = 0; id < SEMMNI; id++)
-          {
-            if (LAdrSem->semary[id] != IPC_UNUSED)
-            {
-              sma = (struct semid_ds *) ((char *) LAdrSem->semary[id] +
-          						(int) LAdrSem) ;
-              if (LAdrSem->state[id] == 1)
-              {
-                for (Index = 0; Index < sma->sem_nsems; Index++)
-                {
-                  name_mangle(100*id+Index, LBuff) ;
-                  LHandle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LBuff) ;
-                  while (WaitForSingleObject(LHandle, 0) == WAIT_OBJECT_0)
-                    ;
-                  LAdrSem->current_nb[id].current_nb[Index] = 0;
-                  CloseHandle(LHandle) ;
-                }
-                LAdrSem->semary[id] = (struct semid_ds *) IPC_UNUSED ;
-                LAdrSem->state[id]  = 0 ;
-              }
-/*
-              else
-              {
-                for (Index = 0; Index < sma->sem_nsems; Index++)
-                {
-                  name_mangle(100*id+Index, LBuff) ;
-                  LHandle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LBuff) ;
-                }
-              }
-*/
-            }
-          } /* for (id ... ) */
-    
-          ReleaseSemaphore(GSemSem, (LONG) 1, &LPrevious) ;
-    
-        /********************************************************************/
-        /* Memoires partagees						*/
-        /* On vire les memoires partagees non referencees			*/
-        /* de temps en temps, on vire les shm dont les pid n'existent plus	*/
-        /********************************************************************/
-    
-          if( LComptShm == 10 )
-          {
-            LComptShm = 0 ;
-            WaitForSingleObject(GSemShm, INFINITE) ;
-    
-            for (id = 0; id < SHMMNI; id++)
-            {
-              if( LAdrShm->shm_segs[id] != (struct shmid_ds *) IPC_UNUSED )
-              {
-                for (Index=0; Index<SHMMNI; Index++)
-                {
-                  if (LAdrShm->shm[id].attaches[Index].pid != 0)
-                  {
-                    LRet = kill(LAdrShm->shm[id].attaches[Index].pid, 0) ;
-                    if( LRet == 0 )
-                    {
-                      break ;
-                    }
-                    else
-                    {
-                      munmap(LAdrShm->shm[id].attaches[Index].adr , LAdrShm->shm[id].shm_segsz ) ;
-                      LAdrShm->shm[id].shm_nattch--;            /* for destruction */
-                      close (LAdrShm->shm[id].attaches[Index].fd) ;
-                      LAdrShm->shm[id].attaches[Index].pid = 0 ;
-                      LAdrShm->shm[id].attaches[Index].adr = 0 ;
-                      LAdrShm->shm[id].attaches[Index].fd  = 0 ;
-                    }
-                  }
-    	    } /* for (Index ... ) */
-/*
-                if( Index == SHMMNI )
-                {
-                  LAdrShm->shm[id].shm_perm.seq++;
-                  LAdrShm->shm_seq = (LAdrShm->shm_seq+1) % ((unsigned)(1<<31)/SHMMNI);
-                  LAdrShm->shm_segs[id] = (struct shmid_ds *) IPC_UNUSED;
-                }
-*/
-              }
-            } /* for (id ... ) */
-    
-            ReleaseSemaphore(GSemShm, (LONG) 1, &LPrevious) ;
-          }
-          else
-          {
-            LComptShm++ ;
-          }
-    
-        } /* end: switch(ret) */
-      }   /* end: while(1) loop */
-      /* Plus besoin
-      WaitForSingleObject(LSemControl, INFINITE) ;
-      */
-    } /* end: able to create new control semaphore */
-  }
-  else
-  {
-    log_message(stderr, LOG_ERR, "IPC-daemon is already started !!") ;
-    return 2;  
-  }
- 
-  goto end ;
- 
-endko: ;
-  log_message(stderr, LOG_ERR, "Unable to start IPC-daemon !") ;
-  return 1 ;  
- 
-end: ;
-  return 0 ; 
+	int iRv;
+	HANDLE LSemControl = NULL;
+	int LFdSem = -1, LFdShm = -1, LFdMsg = -1;
+	CYGWIN_IPCNT_SEMSTR *LAdrSem = (CYGWIN_IPCNT_SEMSTR *)-1;
+	CYGWIN_IPCNT_SHMSTR *LAdrShm = (CYGWIN_IPCNT_SHMSTR *)-1;
+	CYGWIN_IPCNT_MSGSTR *LAdrMsg = (CYGWIN_IPCNT_MSGSTR *)-1;
+	SECURITY_ATTRIBUTES sa;
+
+	HANDLE LHandle ;
+	char LBuff[100] ;
+	int id, Index ;
+	struct semid_ds *sma ;
+	long LPrevious ;
+	int LComptShm = 0 ;
+	int LRet ;
+
+	do {	/* dummy loop */
+		iRv = 1;
+
+		get_null_sa(&sa);
+
+		LSemControl = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE,
+				CYGWIN_IPCNT_SEMCTL) ;
+		if (LSemControl != NULL) {
+			log_message(stderr, LOG_ERR, "IPC-daemon is already started !!") ;
+			iRv = 2;
+			break;
+		}
+
+		LSemControl = CreateSemaphore(tight_security ? NULL : &sa, 0, 1,
+				CYGWIN_IPCNT_SEMCTL) ;
+		if (LSemControl == NULL) {
+			log_message(stderr, LOG_ERR, "Unable to create a semaphore");
+			break;
+		}
+
+		/*********************************************************************/
+		/* Creation des semaphore de gestion des memoires partagees		*/
+		/* Si il existe dans le systeme, On les vire				*/
+		/*********************************************************************/
+		GSemSem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE,
+				CYGWIN_IPCNT_SEMSEM) ;
+		if (GSemSem != NULL) {
+			CloseHandle(GSemSem);
+		}
+
+		GSemSem = CreateSemaphore(tight_security ? NULL : &sa, 1, 1,
+				CYGWIN_IPCNT_SEMSEM) ;
+
+		if (GSemSem == NULL) {
+			log_message(stderr, LOG_ERR, "Unable to create \"Sem\" semaphore");
+			break;
+		}
+
+		GSemShm = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE,
+				CYGWIN_IPCNT_SEMSHM);
+		if (GSemShm != NULL) {
+			CloseHandle(GSemShm);
+		}
+
+		GSemShm = CreateSemaphore(tight_security ? NULL : &sa, 1, 1,
+				CYGWIN_IPCNT_SEMSHM) ;
+		if (GSemSem == NULL) {
+			log_message(stderr, LOG_ERR, "Unable to create \"Shm\" semaphore");
+			break;
+		}
+
+		GSemMsg = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE,
+				CYGWIN_IPCNT_SEMMSG);
+		if (GSemMsg != NULL) {
+			CloseHandle(GSemMsg);
+		}
+
+		GSemMsg = CreateSemaphore(tight_security ? NULL : &sa, 1, 1,
+				CYGWIN_IPCNT_SEMMSG) ; ;
+		if (GSemSem == NULL) {
+			log_message(stderr, LOG_ERR, "Unable to create \"Msg\" semaphore");
+			break;
+		}
+
+		/*********************************************************************/
+		/* Creation des memoires partagees					*/
+		/*********************************************************************/
+
+		/*********************************************************************/
+		/* On commence par le semaphore					*/
+		/*********************************************************************/
+		if (create_map("Sem", &LFdSem, (caddr_t*)&LAdrSem
+				, sizeof(CYGWIN_IPCNT_SEMSTR), CYGWIN_IPCNT_FILESEM
+		) < 0) {
+			break;
+		}
+		sem_init(LAdrSem) ;
+
+		/*********************************************************************/
+		/* On continue par la memoire partagee				*/
+		/*********************************************************************/
+		if (create_map("Shm", &LFdShm, (caddr_t*)&LAdrShm
+				, sizeof(CYGWIN_IPCNT_SHMSTR), CYGWIN_IPCNT_FILESHM
+		) < 0) {
+			break;
+		}
+		shm_init(LAdrShm) ;
+
+		/*********************************************************************/
+		/* On finit par les messages queues					*/
+		/*********************************************************************/
+		if (create_map("Msg", &LFdMsg, (caddr_t*)&LAdrMsg
+				, sizeof(CYGWIN_IPCNT_MSGSTR), CYGWIN_IPCNT_FILEMSG
+		) < 0) {
+			break;
+		}
+		msg_init(LAdrMsg) ;
+
+		hStopEvent = CreateEvent(tight_security ? NULL : &sa,
+				TRUE, FALSE, NULL);
+		if (hStopEvent == NULL) {
+			log_message(stderr, LOG_ERR, "failed to create stop event");
+			break;
+		}
+
+		if (service != 0) {
+			ss.dwCheckPoint = 0;
+			ss.dwWaitHint = 0;
+			ss.dwCurrentState = SERVICE_RUNNING;
+			SetServiceStatus(ssh, &ss);
+			log_message(stderr, LOG_INFO, "'ipc-daemon' service started"); 
+		}
+
+		iRv = 0;
+	} while(0);	/* end dummy loop */
+
+
+	/*********************************************************************/
+	/* On boucle afin de recuperer les Handle des objets crees		*/
+	/* par les fonctions IPC						*/
+	/*********************************************************************/
+
+	/* do not enter if not initialized successfully */
+	while(iRv == 0) {
+		HANDLE hObjects[2];
+		DWORD ret;
+		usleep(300000) ;
+
+		/********************************************************************/
+		/* Semaphores							*/
+		/********************************************************************/
+
+		hObjects[0] = hStopEvent;
+		hObjects[1] = GSemSem;
+		/* The order of the objects matters, since we want the stop-event
+		-* to take precedence over the GSemSem-semaphore which is almost
+		-* always signalled.
+		*/
+
+		ret = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE) ;
+
+		/* switch(ret) */
+		/* case WAIT_OBJECT_0: */
+		if (ret == WAIT_OBJECT_0) {
+			/* got the stop-event */
+			break;
+		}
+
+		/* default: */
+		if (ret != WAIT_OBJECT_0+1) {
+			log_message(stderr, LOG_ERR,
+				"unexpected return from wait, %ld", ret);
+			iRv = 1;
+			break;
+		}
+
+		/* case WAIT_OBJECT_0+1: */
+
+		for (id = 0; id < SEMMNI; id++) {
+			if (LAdrSem->semary[id] == IPC_UNUSED) {
+				continue;
+			}
+			if (LAdrSem->state[id] != 1) {
+				continue;
+			}
+			sma = (struct semid_ds *) (
+				(char *) LAdrSem->semary[id] + (int) LAdrSem
+			);
+
+			/* destroyed: lock semaphores if it still exists */
+			for (Index = 0; Index < sma->sem_nsems; Index++) {
+				name_mangle(100*id+Index, LBuff);
+				LHandle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LBuff);
+				if (LHandle != NULL) {
+					/* someone has this semaphore still open, so lock it
+					*/
+					while (WaitForSingleObject(LHandle, 0) == WAIT_OBJECT_0)
+						;
+					CloseHandle(LHandle) ;
+				}
+				LAdrSem->current_nb[id].current_nb[Index] = 0;
+			}
+			LAdrSem->semary[id] = (struct semid_ds *) IPC_UNUSED;
+			LAdrSem->state[id]  = 0;
+		}
+
+		ReleaseSemaphore(GSemSem, (LONG) 1, &LPrevious) ;
+
+		/********************************************************************/
+		/* Memoires partagees						*/
+		/* On vire les memoires partagees non referencees			*/
+		/* de temps en temps, on vire les shm dont les pid n'existent plus	*/
+		/********************************************************************/
+
+		if (LComptShm < 10) {
+			LComptShm++ ;
+			continue;
+		}
+		LComptShm = 0;
+		WaitForSingleObject(GSemShm, INFINITE);
+
+		for (id = 0; id < SHMMNI; id++) {
+			int nAttached = 0;
+
+			if( LAdrShm->shm_segs[id] == (struct shmid_ds *)IPC_UNUSED) {
+				continue;
+			}
+
+			for (Index=0; Index<SHMMNI; Index++) {
+				if (LAdrShm->shm[id].attaches[Index].pid == 0) {
+					continue;
+				}
+
+				LRet = kill(LAdrShm->shm[id].attaches[Index].pid, 0);
+				if (LRet == 0) {
+					/* attached process is still alive */
+					++ nAttached;
+					continue;
+				}
+				/* attached process died without shmdt.
+				-* do NOT unmap() shm for detached process,
+				-* and do NOT close() file for detached process.
+				-* just invalidate the attaches-entry.
+				*/
+				LAdrShm->shm[id].attaches[Index].pid = 0 ;
+				LAdrShm->shm[id].attaches[Index].adr = 0 ;
+				LAdrShm->shm[id].attaches[Index].fd  = 0 ;
+				LAdrShm->shm[id].shm_nattch--;      /* for destruction */
+			}
+			/* no attached processes any more,
+			-* but shmctl(IPC_RMID) was called while
+			-* other processes did not shmdt() yet,
+			-* destroy it now.
+			*/
+			if (LAdrShm->shm[id].shm_nattch <= 0
+			 && (LAdrShm->shm[id].shm_perm.mode & SHM_DEST) == SHM_DEST
+			) {
+                char LBuff[100] ;
+
+				LAdrShm->shm[id].shm_perm.seq++;
+				LAdrShm->shm_seq =
+					(LAdrShm->shm_seq+1) % ((unsigned)(1<<31)/SHMMNI);
+				LAdrShm->shm_segs[id] = (struct shmid_ds *) IPC_UNUSED;
+
+                strcpy(LBuff, "/tmp/") ;
+                name_mangle(id, LBuff+strlen(LBuff)) ;
+                unlink(LBuff);
+			}
+		}
+
+		ReleaseSemaphore(GSemShm, (LONG) 1, &LPrevious) ;
+	}
+
+	if (iRv != 0) {
+		log_message(stderr, LOG_ERR, "Unable to start IPC-daemon !") ;
+	}
+
+	destroy_map("Msg", &LFdMsg, (caddr_t*)&LAdrMsg
+			, sizeof(CYGWIN_IPCNT_MSGSTR), CYGWIN_IPCNT_FILEMSG);
+	destroy_map("Shm", &LFdShm, (caddr_t*)&LAdrShm
+			, sizeof(CYGWIN_IPCNT_SHMSTR), CYGWIN_IPCNT_FILESHM);
+	destroy_map("Sem", &LFdSem, (caddr_t*)&LAdrSem
+			, sizeof(CYGWIN_IPCNT_SEMSTR), CYGWIN_IPCNT_FILESEM);
+
+	if (LSemControl != NULL) {
+		CloseHandle(LSemControl);
+	}
+
+	return iRv; 
 }
 
 int install_reg_entries(const char *myname, int verbose)
diff -ru cygipc-1.11/sem.c cygipc/sem.c
--- cygipc-1.11/sem.c	Tue Nov 27 00:41:32 2001
+++ cygipc/sem.c	Fri Jan 18 13:25:27 2002
@@ -642,7 +642,7 @@
 		array = arg.array ;
 		va_end(ap);
 
-		for (i=0; i<semnum; i++)
+		for (i=0; i<sma->sem_nsems; i++)
 		{
 		  name_mangle(100*id+i, LBuff) ;
 
@@ -651,13 +651,28 @@
 		    if( LHandle != NULL )
 		    {
 			ReleaseSemaphore(LHandle, array[i], &LPrevious) ;
-	        	shareadrsem->current_nb[id].current_nb[i] +=
+	        	shareadrsem->current_nb[id].current_nb[i] =
 			    array[i] ;
 		    }
 		}
 debug_printf("semctl : SETALL : return 0\n");
 		CYGWIN_IPCNT_RETURN_DECONNECT (0);
 		break;
+
+	case GETALL: /* arg is a pointer to an array of ushort */
+	   va_start(ap, cmd);
+	   arg = va_arg(ap, union semun);
+		array = arg.array ;
+		va_end(ap);
+
+		for (i=0; i<sma->sem_nsems; i++)
+		{
+            array[i] = shareadrsem->current_nb[id].current_nb[i];
+		}
+debug_printf("semctl : GETALL : return 0\n");
+		CYGWIN_IPCNT_RETURN_DECONNECT (0);
+		break;
+
 	case IPC_STAT:
 	   va_start(ap, cmd);
 	   arg = va_arg(ap, union semun);
@@ -687,29 +702,8 @@
 		CYGWIN_IPCNT_RETURN_DECONNECT (-EIDRM);
 	}
 
-	switch (cmd) {
-	case GETALL:
-	   va_start(ap, cmd);
-	   arg = va_arg(ap, union semun);
-	   array = arg.array;
-	   va_end(ap);
-debug_printf("semctl : GETALL return -1\n");
-			CYGWIN_IPCNT_RETURN_DECONNECT (-1);
-		break;
-	case SETALL:
-	   va_start(ap, cmd);
-	   arg = va_arg(ap, union semun);
-		array = arg.array ;
-		va_end(ap);
-debug_printf("semctl : SETALL return -1\n");
-			CYGWIN_IPCNT_RETURN_DECONNECT (-1);
-		break;
-	default:
 debug_printf("semctl : return -EINVAL\n");
-		CYGWIN_IPCNT_RETURN_DECONNECT (-EINVAL);
-	}
-debug_printf("semctl : return 0\n");
-	CYGWIN_IPCNT_RETURN_DECONNECT (0);
+    CYGWIN_IPCNT_RETURN_DECONNECT (-EINVAL);
 }
 
 int semop (int semid, struct sembuf *tsops, unsigned nsops)
diff -ru cygipc-1.11/shm.c cygipc/shm.c
--- cygipc-1.11/shm.c	Sun Feb 11 00:50:02 2001
+++ cygipc/shm.c	Thu Jan 17 14:21:28 2002
@@ -66,6 +66,7 @@
 /*****************************************/
 /*	Initialization of static variables   */
 /*****************************************/
+static pid_t GPProcessId = 0;   /* parent-pid for shmat_atfork_child() */
 static pid_t GProcessId = 0;
 static void init_globals(void)
 {
@@ -108,6 +109,7 @@
  {
   if( IsGSemShmExist() )
   {
+      if (GPProcessId == 0) {
    GFirstShm = 1 ;
    GFdShm  = open(CYGWIN_IPCNT_FILESHM, O_RDWR, 00666 ) ;
    shareadrshm = (CYGWIN_IPCNT_SHMSTR *)
@@ -120,6 +122,7 @@
    }
    ptrshm = &(shareadrshm->shm[0]) ;
    shm_segs = &(shareadrshm->shm_segs[0]);
+      }
   }
   else
   {
@@ -312,6 +315,7 @@
 static void killseg (int id)
 {
 	struct shmid_ds *shp;
+	char LBuff[100] ;
 
 	shp = (struct shmid_ds *)
 			((char *) shm_segs[id] + (int) shm_segs);
@@ -325,6 +329,11 @@
 	shm_segs[id] = (struct shmid_ds *) IPC_UNUSED;
 	if (id == max_shmid)
 		while (max_shmid && (shm_segs[--max_shmid] == IPC_UNUSED));
+
+ 	strcpy(LBuff, "/tmp/") ;
+ 	name_mangle(id, LBuff+strlen(LBuff)) ;
+	unlink(LBuff);
+
 	return;
 }
 
@@ -484,6 +493,77 @@
 	CYGWIN_IPCNT_RETURN_DECONNECT (0) ;
 }
 
+static void shmat_atfork_prepare(void)
+{
+    GPProcessId = GProcessId;
+    return;
+}
+
+static void shmat_atfork_child(void)
+{
+	struct shmid_ds *shp;
+	struct vm_area_struct *pshmd;
+	struct vm_area_struct *shmd;
+	int i, LPid ;
+	unsigned int id;
+
+	LPid = getpid() ;
+
+	if (shm_connect() == 0)
+	{
+debug_printf("shmat_atfork_child : return -EACCESS\n");	
+	 return;
+	}
+    GPProcessId = 0;
+
+    for(id = 0; id < SHMMNI; id++) {
+        if (shm_segs[id] == IPC_UNUSED || shm_segs[id] == IPC_NOID) {
+            continue;
+        }
+
+        shp = (struct shmid_ds *)
+                ((char *) shm_segs[id] + (int) shm_segs);
+        if ((struct shmid_ds *) ((char *) shp-(int)shm_segs) != shm_segs[id]) {
+            continue;
+        }
+
+        for(i = 0; i < SHMMNI; i++) {
+            if (shp->attaches[i].pid == GPProcessId) {
+                break;
+            }
+        }
+        if (i == SHMMNI) {
+            continue;
+        }
+
+        pshmd = &(shp->attaches[i]) ;
+
+        for(i = 0; i < SHMMNI; i++) {
+            if (shp->attaches[i].pid == 0) {
+                break;
+            }
+        }
+        if (i == SHMMNI) {
+debug_printf("shmat_atfork_child : ENOMEM\n");	
+            continue;
+        }
+
+        shmd = &(shp->attaches[i]) ;
+
+        shmd->pid = LPid ;
+        shmd->adr = pshmd->adr;
+        shmd->fd = pshmd->fd;
+
+        shp->shm_nattch++;
+debug_printf("shmat_atfork_child : re-attached\n");	
+    }
+
+debug_printf("shmat_atfork_child : return 0\n");	
+
+    sem_deconnect();
+    return;
+}
+
 /*
  * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists.
  */
@@ -595,6 +675,25 @@
 
 debug_printf("shmat : return %p\n",adr);	
 
+	if (shmd->adr == (caddr_t)-1) {
+		int	eno = -errno;
+		shp->shm_nattch--;
+		close(shmd->fd);
+		shmd->pid = 0;
+		shmd->adr = 0;
+		shmd->fd = 0;
+debug_printf("shmat : return %d\n", eno);	
+		CYGWIN_IPCNT_RETURN_DECONNECT_SHMAT ( eno ) ;
+	}
+
+    {
+        static char atfork_inited = 0;
+        if (atfork_inited == 0) {
+            pthread_atfork(shmat_atfork_prepare, NULL, shmat_atfork_child);
+            atfork_inited = 1;
+        }
+    }
+
 	CYGWIN_IPCNT_RETURN_DECONNECT_SHMAT ( 0 ) ;
 	
 }
@@ -624,9 +723,12 @@
 		((char *) shm_segs[LId] + (int) shm_segs);
 	    if (shm_segs[LId] != IPC_UNUSED)
 	    {
+debug_printf("shmdt : trying shmid %d\n", LId);	
 		for(LIndex = 0; LIndex < SHMMNI; LIndex++ )
 		{
 		    shmd = &(shp->attaches[LIndex]) ;
+debug_printf("shmdt : trying shmid %d/%d (%d/%d/%x)\n",
+    LId, LIndex, shmd->pid, shmd->fd, shmd->adr);	
 		    if( shmd->adr == shmaddr )
 		    {
 			if ( shmd->pid == LPid )
@@ -638,11 +740,9 @@
 			    shmd->adr = 0 ;
 			    shmd->fd  = 0 ;
 			    LFound = 1 ;
+debug_printf("shmdt : detached\n");	
 			    break ;
-			} else {
-debug_printf("shmdt : return -EINVAL\n");	
-	     CYGWIN_IPCNT_RETURN_DECONNECT ( -EINVAL ) ;
-	    }
+			}
 	   }
 	  }
 	  /* No destruction of SHM
@@ -657,6 +757,7 @@
 
 	if( LFound == 0 )
 	{
+debug_printf("shmdt : not found\n");	
 debug_printf("shmdt : return -EINVAL\n");	
 	 CYGWIN_IPCNT_RETURN_DECONNECT ( -EINVAL ) ;
 	}


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]