delorie.com/archives/browse.cgi   search  
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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019