PC shared memory became leak on mac silicon

  apple-m1, c++, macos, memory-leaks, shared-memory

There is an app that builds the following simple source code with Intel. When I run this app on my Mac mini M1 or Macbookair M1, the shared memory seems to be leaking on the way and I can’t allocate a new shared memory segment.
When the COUNT of the source code becomes 341, the shared memory segment can no longer be allocated.
The problem does not occur when run on Intel Mac

However, the problem does not occur when building with M1.
In addition, the second argument of the shmget function seems to be related to PageSize, and it seems that the phenomenon has been cured when this argument was changed to 16384. (Intel PageSize is 4096, Mac mini M1 PageSize is 16384.)

What happened?
Why does the M1 and Intel behave differently like this?
Can you advise me on the right way to solve the problem?

#include <semaphore.h>
#include <unistd.h>
#include <errno.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <mach-o/dyld.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>



#define DS_EXCLUSIVELOCKNAME            "test_ism"
#define Max_Count   10000

struct SOwnerInfo {
    bool    used;
    pid_t    pid;
    
    unsigned int  sleepReq;
};


struct SExclusiveLock
{
    int                shareMemID;
    sem_t            *semaphoreID;
    SOwnerInfo        *ownerInfo;
    FILE            *fp;
};


void DestroyExclusiveLockObject(void *inLockObject)
{
    printf("DestroyExclusiveLockObject startn");
    SExclusiveLock *lock = (SExclusiveLock*) inLockObject;
    int err = 0;
    
    if (lock) {
        if (lock->semaphoreID != (sem_t*)SEM_FAILED)
            ::sem_close(lock->semaphoreID);
        if (lock->ownerInfo != (void*)-1) {
            struct shmid_ds sharedMemDS;
            err = shmdt(lock->ownerInfo);
            if (err == -1) {
                printf("shmdt(lock->ownerInfo) err = %dn", err);
            }
            
            if (lock->shareMemID != -1) {
                err = shmctl(lock->shareMemID, IPC_STAT, &sharedMemDS);
                if (err == -1) {
                    printf("shmctl(lock->shareMemID, IPC_STAT, &sharedMemDS) err = %dn", err);
                }
                if (sharedMemDS.shm_nattch == 0)
                {
                    err = shmctl(lock->shareMemID, IPC_RMID, NULL);
                    if (err == -1) {
                        printf("shmctl(lock->shareMemID, IPC_RMID, NULL) = %dn", err);
                    }
                }
            }
        }
        if (lock->fp)
            fclose(lock->fp);
        lock->fp = NULL;
        free(lock);
        lock = NULL;
    }
    printf("DestroyExclusiveLockObject end err = %dnn", err);
}


void * CreateExclusiveLockObject(const char *inName)
{
    printf("CreateExclusiveLockObject startn");
    char path[256];
    SExclusiveLock *lock = (SExclusiveLock*) malloc(sizeof(SExclusiveLock));
    int size;
    int err = 0;
    
    if (lock) {
        int number = 0;
        
        memset(lock, 0, sizeof(SExclusiveLock));
        lock->shareMemID = -1;
        lock->ownerInfo = (SOwnerInfo *)-1;
        lock->semaphoreID = (sem_t*)SEM_FAILED;
        
        sprintf(path, "/tmp/%s", inName);
        lock->fp = fopen(path, "w");
        if (lock->fp == NULL)
        {
            DestroyExclusiveLockObject(lock);
            lock = NULL;
            printf("ERROR lock->fp == NULLn");
            return lock;
        }
        chmod(path, 0666);
        
        //size = sizeof(SOwnerInfo);
        size = 1024*16;
        lock->shareMemID = ::shmget(::ftok(path, 1), size, IPC_CREAT | 0666);
        if (lock->shareMemID == -1)
        {
            printf("ERROR lock->shareMemID == -1n");
            number = errno;
            printf("lock->shareMemID err = %d(%s)n", number, strerror(number));
            DestroyExclusiveLockObject(lock);
            lock = NULL;
            return lock;
        }
        printf("lock->shareMemID = %dn", lock->shareMemID);
        
        lock->ownerInfo = (SOwnerInfo*) ::shmat(lock->shareMemID, 0, 0666);
        if (lock->ownerInfo == (SOwnerInfo *)-1)
        {
            DestroyExclusiveLockObject(lock);
            lock = NULL;
            printf("ERROR lock->ownerInfo == (SOwnerInfo *)-1n");
            return lock;
        }
        
        lock->semaphoreID = ::sem_open(inName, O_CREAT, 0666, 1);
        if (lock->semaphoreID == (sem_t*)SEM_FAILED)
        {
            DestroyExclusiveLockObject(lock);
            lock = NULL;
            printf("ERROR lock->semaphoreID == (sem_t*)SEM_FAILEDn");
            return lock;
        }
    }
    printf("CreateExclusiveLockObject end err = %dn", err);
    return lock;
}


int main()
{
    int count = 0;
    while (1) {
        printf("COUNT = %dn", count);
        void * test = CreateExclusiveLockObject(DS_EXCLUSIVELOCKNAME);
        if (test)
        {
            sleep(2);
            DestroyExclusiveLockObject(test);
        }
        else { return -1; }
        count ++;
        if (count > Max_Count) { return 0; }
    }
    return 0;
}

Source: Windows Questions C++

LEAVE A COMMENT