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