tags:

views:

40

answers:

1

If I do not define LINUX_ENV macro,everything goes well(especially,the IPC_RMID cmd return 0). but if I define LINUX_ENV(I am running on linux system-ubuntu10.04),the last semctl's IPC_RMID cmd return EINVAL,and says Invalid argument, i.e. the semaphore is not removed. it seems earlier semctl SEM_INFO cmd causes later IPC_RMID cmd return Invalid argument on linux system Where goes wrong in my code?Can anyone help me with this.Thanks in advance.

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//#define LINUX_ENV

#ifdef LINUX_ENV
#define _GNU_SOURCE
#endif

union semun{
    int val;
    struct semid_ds *buf;
    unsigned short int *array;
    struct seminfo *__buf;
};

int main(int argc,char* argv[])
{
    key_t key;
    int semid;
    int nsems;
    int proj_id;

    struct semid_ds semid_ds_buf;
    union semun semun_buf;
    struct seminfo* sem_info;

    proj_id=rand();
    key=ftok(argv[0],proj_id);
    nsems=2;
    semid=semget(key,nsems,IPC_CREAT|IPC_EXCL|0666);
    if(semid==-1)
    {
        perror("semget failed");
        return -1;

    }else
    {
        printf("key(%s,%d) semaphore id:%d\n",argv[0],proj_id,semid);
    }
    semun_buf.buf=&semid_ds_buf;
    //nsems is ignored
    semctl(semid,0,IPC_STAT,&semid_ds_buf);

    printf("current number of semaphores:%lu\n",semid_ds_buf.sem_nsems);

#ifdef LINUX_ENV
    if(semctl(semid,0,SEM_INFO,&semun_buf)==-1)
    {
        printf("semctl SEM_INFO failed");
        return -2;
    }

    sem_info=(struct seminfo*)(&semid_ds_buf);
    printf("max entries in semaphore map:%d\n",sem_info->semmap);

#endif
    if(semctl(semid,0,IPC_RMID,0)==-1)
    {
        perror("semctl IPC-RMID failed");
        return -3;
    }
    return 0;
}
+1  A: 

the SEM_INFO call returns the seminfo struct, defined as follows:

struct  seminfo {
    int semmap;  /* # of entries in semaphore map;
                 unused */
    int semmni;  /* Max. # of semaphore sets */
    int semmns;  /* Max. # of semaphores in all
                 semaphore sets */
    int semmnu;  /* System-wide max. # of undo
                 structures; unused */
    int semmsl;  /* Max. # of semaphores in a set */
    int semopm;  /* Max. # of operations for semop() */
    int semume;  /* Max. # of undo entries per
                 process; unused */
    int semusz;  /* size of struct sem_undo */
    int semvmx;  /* Maximum semaphore value */
    int semaem;  /* Max. value that can be recorded for
                 semaphore adjustment (SEM_UNDO) */
};

set the return buffer to the above structure and try again. hope it helps. (i couldn't recreate your problem using the above code on a RHEL5.4 system though.)


s_b
schemacs
This is because you are sending a pointer to the buffer which gets type-casted to seminfo. semctl() has no way to know that the buffer you sent is not enough to contain the return data, and hence it goes ahead and 'corrupts' the stack , thereby causing the next semctl() call to behave erratically.
s_b
Thanks.It's my fault to do that.
schemacs