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/

Reply via email to