Mail Archives: cygwin/2005/04/04/02:52:12
--------------050504050105030800080702
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
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
--------------050504050105030800080702
Content-Type: text/plain;
name="fork-ipc-sem2.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="fork-ipc-sem2.c"
#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);
}
--------------050504050105030800080702
Content-Type: text/plain; charset=us-ascii
--
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/
--------------050504050105030800080702--
- Raw text -