Corinna Vinschen wrote :
Thanks again for the testcase. It helped to track down the problem which was a result of my previous check in. It should be solved in CVS now.
Since you're building from CVS anyway, I don't create another snapshot
for now. We're that close to 1.5.14 anyway...
Thanks again for having solved this so quickly.
However, semaphores still doesn't work properly.
There is no more problem with semop not waiting, but with quick semaphores locking unlocking.
I attach a new testcase, which is the same as previous one, except each child task will lock the semaphore, wait 100ms, then release the semaphore and die. Each time a child dies, a new one is created to keep 10 running childs.
On osx, you will see forever locking/unlocking of semaphore written on output.
On lastest cygwin, you will see some locking/unlocking (about 11 or 12 lock/unlock pair for me), then every child keep waiting for locking, and the program comes in dead-lock.
I think that semop doesn't get awaken properly when semaphore value change quickly.
Same conditions (windows/cygwin version), as previous mail apply.
Kraken
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <signal.h> #include <sys/wait.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/errno.h>
#define USE_IPC #define USE_SEM //define BIND_AFTER_FORK #define BUFFERLEN 256 struct database { int shmid; int semid; int test1; int test2; } *wdb; int get_shared_memory(char *path_key) { key_t key; int shmid; int shmflg; char file[BUFFERLEN]; snprintf(file, BUFFERLEN-1, "%s.exe", path_key); if ((key = ftok(file, 'Z')) == -1) { perror("Getting key for shared memory"); exit(1); } shmflg = IPC_CREAT|0600; if ((shmid = shmget(key, sizeof(struct database), shmflg)) == -1) { perror ("Getting shared memory"); exit(1); } fprintf(stderr,"shmid: %i\n", shmid); return (shmid); } int get_semaphores(char *path_key) { key_t key; int semid; struct sembuf op; int semflg; char file[BUFFERLEN]; snprintf(file, BUFFERLEN-1, "%s.exe", path_key); if ((key = ftok(file, 'Z')) == -1) { perror("Getting key for semaphores"); exit(1); } semflg = IPC_CREAT|0600; if ((semid = semget(key, 1, semflg)) == -1) { perror("Getting semaphores"); exit(1); } if (semctl(semid, 0, SETVAL, 1) == -1) { perror("semctl SETVAL -> 1"); exit(1); } if (semctl(semid, 0, GETVAL) == 0) { op.sem_num = 0; op.sem_op = 1; op.sem_flg = 0; if (semop(semid, &op, 1) == -1) { perror("semaphore_release"); exit(1); } } fprintf(stderr,"semval: %i semid: %i\n", semctl (semid, 0, GETVAL), semid); return (semid); } void *attach_shared_memory(int shmid) { void *rv; // return value if ((rv = shmat(shmid, 0, 0)) == (void *) -1) { perror("shmat"); return ((void *) -1); } return (rv); } int detach_shared_memory(void *shmaddr) { int rv; // return value if ((rv = shmdt(shmaddr)) == -1) { perror("shmdt"); return (-1); } return (rv); } void set_signal_handlers (void) { struct sigaction ignore; ignore.sa_handler = SIG_IGN; sigemptyset(&ignore.sa_mask); ignore.sa_flags = 0; sigaction(SIGHUP, &ignore, NULL); // So we keep running as a daemon } int get_socket(short port) { int sfd; //socket file descriptor struct sockaddr_in addr; int opt; opt = 1; sfd = socket(PF_INET, SOCK_STREAM, 0); if (sfd == -1) { perror("socket"); exit(1); } else { if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (int *) &opt, sizeof(opt)) == -1) perror ("setsockopt"); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sfd, (struct sockaddr *) &addr, sizeof (addr)) == -1) { perror("bind"); sfd = -1; } else { listen (sfd, 5); } } return (sfd); } int accept_socket (int sfd, struct sockaddr_in *addr) { int fd; int len = sizeof(struct sockaddr_in); if ((fd = accept(sfd, (struct sockaddr *) addr, &len)) == -1) { perror("Accepting connection\n"); exit(1); } return (fd); } void semaphore_lock(int semid) { struct sembuf op; op.sem_num = 0; op.sem_op = -1; op.sem_flg = SEM_UNDO; fprintf(stderr,"Locking... semval: %i semid: %i\n",semctl (semid,0,GETVAL),semid); if (semop(semid, &op, 1) == -1) { perror("semaphore_lock"); printf("%i\n",errno); exit(0); } fprintf(stderr,"Locked !!! semval: %i semid: %i\n",semctl (semid,0,GETVAL),semid); } void semaphore_release(int semid) { struct sembuf op; fprintf(stderr,"Unlocking... semval: %i semid: %i\n",semctl (semid,0,GETVAL),semid); op.sem_num = 0; op.sem_op = 1; op.sem_flg = SEM_UNDO; if (semop(semid, &op, 1) == -1) { perror ("semaphore_release"); printf("%i\n",errno); exit(0); } fprintf(stderr,"Unlocked !!! semval: %i semid: %i\n",semctl (semid,0,GETVAL),semid); } int main(int argc, char *argv[]) { int sfd; // socket file descriptor int csfd; // child sfd, the socket once accepted int shmid; // shared memory id int semid; // semaphore id struct sockaddr_in addr; // Address of the remote host pid_t child; pid_t child_wait; int n_children; int rc; // Return code int i; // For loops n_children = 0; set_signal_handlers(); #ifdef USE_IPC shmid = get_shared_memory(argv[0]); semid = get_semaphores(argv[0]); if ((wdb = attach_shared_memory(shmid)) == (void *) -1) exit (1); wdb->shmid = shmid; wdb->semid = semid; #endif #ifndef BIND_AFTER_FORK if ((sfd = get_socket(1234)) == -1) exit(0); #endif printf ("Waiting for connections...\n"); while (1) { if (n_children < 10) { if ((child = fork()) == 0) { #ifdef BIND_AFTER_FORK if ((sfd = get_socket(1234)) == -1) exit(0); #endif #ifdef USE_SEM semaphore_lock(wdb->semid); usleep(100); semaphore_release(wdb->semid); #endif exit(0); } else if (child != -1) n_children++; else perror("Forking\n"); } else { if ((child_wait = wait (&rc)) != -1) n_children--; } } exit(0); }
-- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/