There seems to be bug in $SUBJ. When I run attached program on recent -CURRENT, it always (after several seconds) triggers the bug. I first suspected a problem in the program's logic but on stable in runs just fine.
Esentially I use piece of shm memory to pass some data between several processes. I implemented simple locking functions with semaphores and noticed it behaves strange on -CURRENT and ok on -STABLE. CCing Alfred because he made some changes into the kernel part of $SUBJ. I don't expect the bug is new though. May I ask someone with older -CURRENT to try running the program for a minute? -- Michal Mertl [EMAIL PROTECTED]
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #define MY_SHM_MAGIC 0x56d9f13b typedef struct { struct shmid_ds shm_ds; struct semid_ds sem_ds; pid_t sem_owner; int sem_id; int shm_id; int size; } s_ipc_cfg; s_ipc_cfg *ipc_cfg = NULL; int ipc_setup(int size) { int skey; int ipc_tok; void *shm_addr; struct shmid_ds shm_ds; union semun sem_arg; ipc_tok = IPC_PRIVATE; if ((skey = shmget(ipc_tok, size, SHM_R | SHM_W | IPC_CREAT)) == -1) { fprintf(stderr, "shmget()\n"); return (-1); } if ((shmctl(skey, IPC_STAT, &shm_ds)) == -1) { fprintf(stderr, "shmctl()\n"); return (-1); } if ((shm_addr = shmat(skey, NULL, 0)) == (void *)-1) { fprintf(stderr, "shmat()\n"); return (-1); } ipc_cfg = shm_addr; ipc_cfg->size = size - sizeof(s_ipc_cfg); memcpy(ipc_cfg, &shm_ds, sizeof(shm_ds)); ipc_cfg->shm_id = skey; if (shmctl(ipc_cfg->shm_id, IPC_RMID, NULL) == -1) { fprintf(stderr, "shmctl() IPC_RMID\n"); return (-1); } if ((skey = semget(ipc_tok, 1, SEM_R | SEM_A | IPC_CREAT)) == -1) { fprintf(stderr, "semget()\n"); return (-1); } ipc_cfg->sem_id = skey; sem_arg.buf = (void *)&ipc_cfg->sem_ds; if (semctl(ipc_cfg->sem_id, 0, IPC_STAT, sem_arg) == -1) { fprintf(stderr, "semctl()\n"); return (-1); } ipc_cfg->sem_owner = -1; sem_arg.val = 1; semctl(ipc_cfg->sem_id, 0, SETVAL, sem_arg); return (0); } void ipc_shutdown(void) { if (ipc_cfg) semctl(ipc_cfg->sem_id, 0, IPC_RMID); } int ipc_lock(int wait, int undo) { struct sembuf sem_buf; int err; sem_buf.sem_num = 0; sem_buf.sem_op = -1; sem_buf.sem_flg = wait ? 0 : IPC_NOWAIT; sem_buf.sem_flg |= undo ? SEM_UNDO : 0; err = semop(ipc_cfg->sem_id, &sem_buf, 1); if (err == -1) { if (wait && errno == EAGAIN) return (-2); fprintf(stderr, "%d: semop()\n", getpid()); return (-1); } printf("%d: ipc_lock()\n", getpid()); ipc_cfg->sem_owner = getpid(); return (0); } int ipc_unlock(void) { struct sembuf sem_buf; int err; if (ipc_cfg->sem_owner != getpid()) { fprintf(stderr, "%d: can't unlock (bug), owner: %d\n", getpid(), ipc_cfg->sem_owner); return (-1); } if (semctl(ipc_cfg->sem_id, 0, GETVAL) != 0) { fprintf(stderr, "%d: can't unlock (bug), not locked\n", getpid()); return (-1); } printf("%d: ipc_unlock()\n", getpid()); sem_buf.sem_num = 0; sem_buf.sem_op = 1; sem_buf.sem_flg = 0; err = semop(ipc_cfg->sem_id, &sem_buf, 1); if (err == -1) { fprintf(stderr, "%d: semop()\n", getpid()); return (-1); } ipc_cfg->sem_owner = -1; return (0); } int ipc_locked(void) { return (semctl(ipc_cfg->sem_id, 0, GETVAL) ? 0 : 1); } int ipc_owned(void) { return (ipc_locked() && ipc_cfg->sem_owner == getpid() ? 1 : 0); } int ipc_useit(void) { if (!ipc_owned()) { if (ipc_lock(1, 0) < 0) { printf("%d: _ipc_getpart() can't lock\n", getpid()); return (-1); } } if (ipc_unlock() < 0) { fprintf(stderr, "%d: _ipc_getpart() can't unlock\n", getpid()); return (-1); } return (0); } int be_child(void) { for (;;) { usleep(10000 + random() % 5000); ipc_useit(); } return (0); } int main(int argc, char *argv[]) { srandomdev(); if (ipc_setup(10000) < 0) { fprintf(stderr, "ipc_setup failed\n"); return (EXIT_FAILURE); } switch (fork()) { case 0: /* child */ be_child(); return (EXIT_SUCCESS); break; case -1: fprintf(stderr, "fork failed\n"); ipc_shutdown(); return (EXIT_FAILURE); default: /* parent */ ; } if (atexit(ipc_shutdown) < 0) { fprintf(stderr, "atexit()\n"); return (EXIT_FAILURE); } for (;;) { usleep(15000 + random() % 5000); ipc_useit(); } return (EXIT_SUCCESS); }