This is the mail archive of the cygwin 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]

Re: ipc, sockets and windows sp2


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/

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