This is the mail archive of the
cygwin
mailing list for the Cygwin project.
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/