- added a check for broken RH5 include files. With the standard RH5
[kai/samba.git] / source3 / locking / shmem_sysv.c
index 14ed199738d9b46c0eed9c9a927c4eb06cc83363..b9d45949479ccd4f8de768adc1bf117042948020 100644 (file)
@@ -2,7 +2,7 @@
    Unix SMB/Netbios implementation.
    Version 1.9.
    Shared memory functions - SYSV IPC implementation
-   Copyright (C) Andrew Tridgell 1997
+   Copyright (C) Andrew Tridgell 1997-1998
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -39,6 +39,7 @@ extern int DEBUGLEVEL;
 #define IPC_PERMS 0644
 #endif
 
+
 #ifdef SECURE_SEMAPHORES
 /* secure semaphores are slow because we have to do a become_root()
    on every call! */
@@ -119,7 +120,7 @@ static BOOL sem_change(int i, int op)
 
        sb.sem_num = i;
        sb.sem_op = op;
-       sb.sem_flg = SEM_UNDO;
+       sb.sem_flg = 0;
 
        ret = semop(sem_id, &sb, 1);
 
@@ -539,6 +540,16 @@ struct shmem_ops *sysv_shm_open(int ronly)
        struct semid_ds sem_ds;
        union semun su;
        int i;
+       int pid;
+
+
+
+#ifdef LINUX
+       if (sizeof(shm_ds) == 52) {
+               DEBUG(0,("WARNING: You probably have a broken set of glibc2 include files - disabling sysv shared memory\n"));
+               return NULL;
+       }
+#endif
 
        read_only = ronly;
 
@@ -556,8 +567,9 @@ struct shmem_ops *sysv_shm_open(int ronly)
                while (hash_size > 1) {
                        sem_id = semget(SEMAPHORE_KEY, hash_size+1, 
                                        IPC_CREAT|IPC_EXCL| SEMAPHORE_PERMS);
-                       if (sem_id != -1 || errno != EINVAL) break;
-                       hash_size--;
+                       if (sem_id != -1 || 
+                           (errno != EINVAL && errno != ENOSPC)) break;
+                       hash_size -= 5;
                }
 
                if (sem_id == -1) {
@@ -595,6 +607,16 @@ struct shmem_ops *sysv_shm_open(int ronly)
                        return NULL;
                }
 
+               if (semctl(sem_id, 0, GETVAL, su) == 0 &&
+                   !process_exists((pid=semctl(sem_id, 0, GETPID, su)))) {
+                       DEBUG(0,("WARNING: clearing global IPC lock set by dead process %d\n",
+                                pid));
+                       su.val = 1;
+                       if (semctl(sem_id, 0, SETVAL, su) != 0) {
+                               DEBUG(0,("ERROR: Failed to clear global lock\n"));
+                       }
+               }
+
                sem_ds.sem_perm.mode = SEMAPHORE_PERMS;
                if (semctl(sem_id, 0, IPC_SET, su) != 0) {
                        DEBUG(0,("ERROR shm_open : can't IPC_SET\n"));
@@ -605,6 +627,19 @@ struct shmem_ops *sysv_shm_open(int ronly)
        
        if (!global_lock())
                return NULL;
+
+
+       for (i=1;i<hash_size+1;i++) {
+               if (semctl(sem_id, i, GETVAL, su) == 0 && 
+                   !process_exists((pid=semctl(sem_id, i, GETPID, su)))) {
+                       DEBUG(1,("WARNING: clearing IPC lock %d set by dead process %d\n", 
+                                i, pid));
+                       su.val = 1;
+                       if (semctl(sem_id, i, SETVAL, su) != 0) {
+                               DEBUG(0,("ERROR: Failed to clear IPC lock %d\n", i));
+                       }
+               }
+       }
        
        /* try to use an existing key */
        shm_id = shmget(SHMEM_KEY, shm_size, 0);
@@ -615,8 +650,9 @@ struct shmem_ops *sysv_shm_open(int ronly)
                while (shm_size > MIN_SHM_SIZE) {
                        shm_id = shmget(SHMEM_KEY, shm_size, 
                                        IPC_CREAT | IPC_EXCL | IPC_PERMS);
-                       if (shm_id != -1 || errno != EINVAL) break;
-                       shm_size *= 0.9;
+                       if (shm_id != -1 || 
+                           (errno != EINVAL && errno != ENOSPC)) break;
+                       shm_size *= 0.8;
                }
                created_new = (shm_id != -1);
        }