Mail Archives: cygwin/2012/11/19/11:05:46
X-Recipient: | archive-cygwin AT delorie DOT com
|
X-SWARE-Spam-Status: | No, hits=-2.5 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,RP_MATCHES_RCVD,SPF_HELO_PASS
|
X-Spam-Check-By: | sourceware.org
|
X-IronPortListener: | Outbound_SMTP
|
X-IronPort-Anti-Spam-Filtered: | true
|
X-IronPort-Anti-Spam-Result: | AgMJAA1YqlCcKEel/2dsb2JhbABFw0KBAQeCIAEEEhUTUQEVFRQvEyYBBBsah2ueZYROnE2QYGEDjTGOWIM2DoZygm+CGQ
|
From: | "Lavrentiev, Anton (NIH/NLM/NCBI) [C]" <lavr AT ncbi DOT nlm DOT nih DOT gov>
|
To: | "cygwin AT cygwin DOT com" <cygwin AT cygwin DOT com>
|
Subject: | SYSV semaphore bug (testcase attached)
|
Date: | Mon, 19 Nov 2012 16:04:51 +0000
|
Message-ID: | <5F8AAC04F9616747BC4CC0E803D5907D012656@MLBXV09.nih.gov>
|
MIME-Version: | 1.0
|
X-IsSubscribed: | yes
|
Mailing-List: | contact cygwin-help AT cygwin DOT com; run by ezmlm
|
List-Id: | <cygwin.cygwin.com>
|
List-Subscribe: | <mailto:cygwin-subscribe AT cygwin DOT com>
|
List-Archive: | <http://sourceware.org/ml/cygwin/>
|
List-Post: | <mailto:cygwin AT cygwin DOT com>
|
List-Help: | <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
|
Sender: | cygwin-owner AT cygwin DOT com
|
Mail-Followup-To: | cygwin AT cygwin DOT com
|
Delivered-To: | mailing list cygwin AT cygwin DOT com
|
X-MIME-Autoconverted: | from quoted-printable to 8bit by delorie.com id qAJG5gPX028713
|
Hi,
As I previously reported, there is a weird behavior of CYGWIN implementation
of SYSV semaphores, and a bug exposition for one problem is attached below
(I'm still looking into some other issues in there).
If the code is compiled with both BUG1 and BUG2 defined (as shown), it
will abort at iteration 16384 (just the default semaphore overflow).
Undefining BUG2 causes the problem disappear (because there is no longer
UNDO on the 1st semaphore). Also, running the code with just one semaphore
(undef BUG1) causes no problem. Finally, replacing "#if 1" with "#if 0"
to unlock the semaphore allows to run indefinitely with any combination of
BUG1/2 (just remember to issue ipcs/ipcrm to start with a clean slate at
all times).
Reviewing the code of CYGSERVER, there is an apparent bug in the semundo_clear()
routine (at around line 536, which looks like "i++, sunptr++;", and advances
both undo indexes even when "if (sunptr->un_id == semid)" (line 524)
failed to match semid. This means that for two (or more) semaphores, the
undo index "i" moves ahead even when nothing was done while still searching.
This causes the adjust pointer to miss the position to clear, and overflow
the semaphore adjust value (line 1207, semop(), by the virtue of
semundo_adjust()'s logic at about line 486).
#include <errno.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define BUG1
#define BUG2
#define SEMKEY 1
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* array for GETALL, SETALL */
};
static void doCriticalWork(void)
{
return;
}
int main(void)
{
struct sembuf lock[2];
int n, semid;
if ((semid = semget(SEMKEY, 2, IPC_CREAT | 0666)) < 0) {
perror("semget(IPC_CREATE)");
return 1;
}
#ifdef BUG1
lock[0].sem_num = 0;
lock[0].sem_op = 0;
lock[0].sem_flg = IPC_NOWAIT;
lock[1].sem_num = 0;
lock[1].sem_op = 1;
#ifdef BUG2
lock[1].sem_flg = SEM_UNDO;
#else
lock[1].sem_flg = 0;
#endif
if (semop(semid, lock, 2) != 0) {
perror("semop(LOCK[0])");
return 1;
}
#endif
for (n = 0; ; ++n) {
static const union semun arg = { 0 };
int error;
printf("Iteration %d\n", n);
lock[0].sem_num = 1;
lock[0].sem_op = 0; /* precondition: [1] == 0 */
lock[0].sem_flg = 0;
lock[1].sem_num = 1;
lock[1].sem_op = 1; /* postcondition: [1] == 1 */
lock[1].sem_flg = SEM_UNDO;
if (semop(semid, lock, 2) < 0) {
error = errno;
fprintf(stderr, "semop(LOCK[1]): %d, %s\n",
error, strerror(error));
break;
}
doCriticalWork();
#if 1
if (semctl(semid, 1, SETVAL, arg) < 0) {
error = errno;
fprintf(stderr, "semctl(UNLOCK[1]): %d, %s\n",
error, strerror(error));
break;
}
#else
lock[0].sem_num = 1;
lock[0].sem_op = -1;
lock[0].sem_flg = SEM_UNDO | IPC_NOWAIT;
if (semop(semid, lock, 1) < 0) {
error = errno;
fprintf(stderr, "semop(UNLOCK[1]): %d, %s\n",
error, strerror(error));
break;
}
#endif
}
return 1;
}
Anton Lavrentiev
Contractor NIH/NLM/NCBI
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
- Raw text -