Bug on Posix IPC_STAT. Wrong number of attachments

tcak via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Jan 18 10:07:04 PST 2015


On Sunday, 18 January 2015 at 16:06:39 UTC, tcak wrote:
> I create a shared memory by using shmget. And attach to it by 
> using shmat.
>
> Finally, I use shmctl to get statistics to learn number of 
> attachments to
> that shared memory. According to documentation 
> (linux.die.net/man/2/shmat), number of attachments should be 1.
>
> Same codes, C returns 1, D returns 0. It took me 2 days until 
> realising this.
>
> I put C and D codes, and makefile for quick testing.
>
> Ubuntu 64-bit. Kernel: 3.13.0-44-generic
>
> I checked the shmid_ds at both "core.sys.posix.sys.shm" and 
> "/usr/include/bits/shm.h". They look similar. Although C 
> definition makes a difference based on 32 and 64 bits, D's 
> definition doesn't care about. Because I am on 64-bit kernel, 
> they should be same.
>
>
>
> main.c
> ==========================
> #include <stdio.h>
> #include <sys/types.h>
> #include <sys/ipc.h>
> #include <sys/shm.h>
> #include <fcntl.h>
>
> void main(){
> 	// allocate
> 	int id = shmget( IPC_PRIVATE, 4096, IPC_CREAT | S_IRUSR | 
> S_IWUSR );
>
> 	// if failed, leave
> 	if( id == -1 ){
> 		printf("shmget failed\n");
> 		return;
> 	}
>
> 	// attach
> 	void* ptr = shmat( id, 0, 0 );
>
> 	// if failed, leave
> 	if( ptr == (void*)-1 ){
> 		printf("shmat failed\n");
> 		shmctl( id, IPC_RMID, 0 );
> 		return;
> 	}
>
> 	// stat
> 	struct shmid_ds stat;
>
> 	// get statistics
> 	int res = shmctl( id, IPC_STAT, &stat );
> 	printf("STAT: %d\n", res);
>
> 	// get number of attachments
> 	printf("NATTCH: %d\n", (unsigned short)stat.shm_nattch);
>
> 	// detach
> 	shmdt( ptr );
>
> 	// remove
> 	shmctl( id, IPC_RMID, 0 );
> }
>
>
> main.d
> ===============================
> import std.stdio;
>
> private import core.sys.posix.sys.mman;
> private import core.sys.posix.sys.shm;
> private import core.sys.posix.unistd;
> private import core.sys.posix.sys.stat;
> private static import core.stdc.errno;
> private static import core.stdc.time;
>
> void main(){
> 	// allocate
> 	int id = shmget( IPC_PRIVATE, 4096, IPC_CREAT | S_IRUSR | 
> S_IWUSR );
>
> 	// if failed, leave
> 	if( id == -1 ){
> 		writeln("shmget failed");
> 		return;
> 	}
>
> 	// attach
> 	void* ptr = shmat( id, null, 0 );
>
> 	// if failed, leave
> 	if( ptr == cast(void*)-1 ){
> 		writeln("shmat failed");
> 		shmctl( id, IPC_RMID, null );
> 		return;
> 	}
>
> 	// stat
> 	shmid_ds stat;
>
> 	// get statistics
> 	int res = shmctl( id, IPC_STAT, &stat );
> 	writeln("STAT: ", res);
>
> 	// get number of attachments
> 	writeln("NATTCH: ", stat.shm_nattch);
>
> 	// detach
> 	shmdt( ptr );
>
> 	// remove
> 	shmctl( id, IPC_RMID, null );
> }
>
>
>
> makefile
> ==============================
> all:
> 	dmd main.d -of"dprog"
> 	gcc main.c -o cprog
>
> clear:
> 	rm cprog
> 	rm dprog


Here is what I did to solve the problem. In D code, I defined my 
own shmid_ds struct (Structure is taken from 
/usr/include/bits/shm.h)

// from /usr/include/bits/shm.h
/* Type to count number of attaches.  */
alias shmatt_t = c_ulong;

/* Data structure describing a shared memory segment.  */
version( X86_64 ){
	struct my_shmid_ds{
	    ipc_perm shm_perm;		/* operation permission struct */
	    size_t shm_segsz;			/* size of segment in bytes */
	    time_t shm_atime;			/* time of last shmat() */
	    time_t shm_dtime;			/* time of last shmdt() */
	    time_t shm_ctime;			/* time of last change by shmctl() */
	    pid_t shm_cpid;			/* pid of creator */
	    pid_t shm_lpid;			/* pid of last shmop */
	    shmatt_t shm_nattch;		/* number of current attaches */
	    c_ulong __glibc_reserved4;
	    c_ulong __glibc_reserved5;
	};
}
else{
	struct my_shmid_ds{
	    ipc_perm shm_perm;		/* operation permission struct */
	    size_t shm_segsz;			/* size of segment in bytes */
	    time_t shm_atime;			/* time of last shmat() */
	    c_ulong __glibc_reserved1;
	    time_t shm_dtime;			/* time of last shmdt() */
	    c_ulong __glibc_reserved2;
	    time_t shm_ctime;			/* time of last change by shmctl() */
	    c_ulong __glibc_reserved3;
	    pid_t shm_cpid;			/* pid of creator */
	    pid_t shm_lpid;			/* pid of last shmop */
	    shmatt_t shm_nattch;		/* number of current attaches */
	    c_ulong __glibc_reserved4;
	    c_ulong __glibc_reserved5;
	};
}



Then, I changed the type of "stat" variable:

my_shmid_ds stat;



Finally, need to do a casting (Doing this came to me so stupid 
after writing it in C):

int res = shmctl( id, IPC_STAT, cast( 
core.sys.posix.sys.shm.shmid_ds* )(&stat) );


After these, it works perfectly. I hope this can be fixed in next 
version.


More information about the Digitalmars-d-learn mailing list