All of lore.kernel.org
 help / color / mirror / Atom feed
* A root cause of "unable to create IPC shm instance"
@ 2015-12-10 11:04 IceBsi
  2015-12-10 11:30 ` Jaroslav Kysela
  0 siblings, 1 reply; 2+ messages in thread
From: IceBsi @ 2015-12-10 11:04 UTC (permalink / raw)
  To: alsa-devel@alsa-project.org

Dear ALSA developers:

I found a root cause of the following issue by using strace:
    unable to create IPC shm instance

Firstly, please see the test code below:
  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <sys/ipc.h>
  4 #include <sys/shm.h>
  5 #include <errno.h>
  6 #include <string.h>
  7 
  8 int main(int argc, char *argv[])
  9 {
 10 	int r = 0;
 11 	struct shmid_ds buf;
 12 	key_t ipc_key = (key_t)325559;
 13 	size_t shmsize = 488;
 14 	int shmid = -1;
 15 	mode_t ipc_perm = 0666;
 16 	void *shmptr = NULL;
 17 	pid_t pid;
 18 
 19 	printf("___%d:%d call shmget(%d,%u,%d)\n", __LINE__, getpid(), (int)(ipc_key), shmsize, IPC_CREAT | ipc_perm);
 20 	shmid = shmget(ipc_key, shmsize, IPC_CREAT | ipc_perm);
 21 	printf("___%d:%d ret shmget=%d\n", __LINE__, getpid(), shmid);
 22 
 23 	printf("___%d:%d call shmat(%d,0,0)\n", __LINE__, getpid(), shmid);
 24 	shmptr = shmat(shmid, 0, 0);
 25 	printf("___%d:%d ret shmat=%p\n", __LINE__, getpid(), shmptr);
 26 
 27 	printf("+++%d:%d call fork\n", __LINE__, getpid());
 28 	pid = fork();
 29 	printf("+++%d:%d ret fork=%d\n", __LINE__, getpid(), (int)pid);
 30 
 31 	printf("___%d:%d call shmctl(%d,IPC_STAT,%p)\n", __LINE__, getpid(), shmid, &buf);
 32 	r = shmctl(shmid, IPC_STAT, &buf);
 33 	printf("___%d:%d ret shmctl=%d\n", __LINE__, getpid(), r);
 34 	printf("___%d:%d nattch=%lu\n", __LINE__, getpid(), buf.shm_nattch);
 35 
 36 	printf("___%d:%d call shmdt(%p)\n", __LINE__, getpid(), shmptr);
 37 	r = shmdt(shmptr);
 38 	printf("___%d:%d ret shmdt=%d\n", __LINE__, getpid(), r);
 39 
 40 	printf("___%d:%d call shmctl(%d,IPC_RMID,NULL)\n", __LINE__, getpid(), shmid);
 41 	r = shmctl(shmid, IPC_RMID, NULL);
 42 	printf("___%d:%d ret shmctl=%d, %s\n", __LINE__, getpid(), r, strerror(errno));
 43 
 44 	if ((pid_t)0 != pid) {
 45 		printf("+++%d:%d call wait(NULL)\n", __LINE__, getpid());
 46 		pid = wait(NULL);
 47 		printf("+++%d:%d ret wait=%d\n", __LINE__, getpid(), (int)pid);
 48 	}
 49 
 50 	return 0;
 51 }
The output of the test code is:
___19:11782 call shmget(325559,488,950)
___21:11782 ret shmget=2850820
___23:11782 call shmat(2850820,0,0)
___25:11782 ret shmat=0x7f452c223000
+++27:11782 call fork
+++29:11782 ret fork=11783
___31:11782 call shmctl(2850820,IPC_STAT,0x7fffdaf0a750)
___33:11782 ret shmctl=0
___34:11782 nattch=2
___36:11782 call shmdt(0x7f452c223000)
+++29:11783 ret fork=0
___38:11782 ret shmdt=0
___40:11782 call shmctl(2850820,IPC_RMID,NULL)
___31:11783 call shmctl(2850820,IPC_STAT,0x7fffdaf0a750)
___42:11782 ret shmctl=0, Success
+++45:11782 call wait(NULL)
___33:11783 ret shmctl=0
___34:11783 nattch=1
___36:11783 call shmdt(0x7f452c223000)
___38:11783 ret shmdt=0
___40:11783 call shmctl(2850820,IPC_RMID,NULL)
___42:11783 ret shmctl=-1, Invalid argument
+++47:11782 ret wait=11783
And sometimes output is:
___19:11798 call shmget(325559,488,950)
___21:11798 ret shmget=3112964
___23:11798 call shmat(3112964,0,0)
___25:11798 ret shmat=0x7f6b39378000
+++27:11798 call fork
+++29:11798 ret fork=11799
___31:11798 call shmctl(3112964,IPC_STAT,0x7fff3a6472a0)
___33:11798 ret shmctl=0
+++29:11799 ret fork=0
___31:11799 call shmctl(3112964,IPC_STAT,0x7fff3a6472a0)
___34:11798 nattch=2
___36:11798 call shmdt(0x7f6b39378000)
___33:11799 ret shmctl=0
___38:11798 ret shmdt=0
___34:11799 nattch=2
___40:11798 call shmctl(3112964,IPC_RMID,NULL)
___36:11799 call shmdt(0x7f6b39378000)
___42:11798 ret shmctl=0, Success
+++45:11798 call wait(NULL)
___38:11799 ret shmdt=0
___40:11799 call shmctl(3112964,IPC_RMID,NULL)
___42:11799 ret shmctl=-1, Invalid argument
+++47:11798 ret wait=11799
>From the outputs the parent process always get nattch=2, the child process
get nattch=1 or sometimes get nattch=2.

Then please see the following lines of src/pcm/pcm_direct.c
(from alsa-lib-1.1.0.tar.bz2):
 110 	dmix->shmptr = shmat(dmix->shmid, 0, 0);
 111 	if (dmix->shmptr == (void *) -1) {
 112 		err = -errno;
 113 		snd_pcm_direct_shm_discard(dmix);
 114 		return err;
 115 	}
 116 	mlock(dmix->shmptr, sizeof(snd_pcm_direct_share_t));
 117 	if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) {
 118 		err = -errno;
 119 		snd_pcm_direct_shm_discard(dmix);
 120 		return err;
 121 	}
 122 	if (buf.shm_nattch == 1) {      /* we're the first user, clear the segment */
 123 		memset(dmix->shmptr, 0, sizeof(snd_pcm_direct_share_t));
 124 		if (dmix->ipc_gid>= 0) {
 125 			buf.shm_perm.gid = dmix->ipc_gid;
 126 			shmctl(dmix->shmid, IPC_SET, &buf);
 127 		}
 128 		dmix->shmptr->magic = SND_PCM_DIRECT_MAGIC;
 129 		return 1;
 130 	} else {
 131 		if (dmix->shmptr->magic != SND_PCM_DIRECT_MAGIC) {
 132 			snd_pcm_direct_shm_discard(dmix);
 133 			return -EINVAL;
 134 		}
 135 	}
If an applicatioin that uses alsa-lib invokes fork() and the fork() is invoked
just after shmat(line 110) and just before shmctl(line 117), buf.shm_nattch
will be 2, so "buf.shm_nattch == 1" will be false. But while buf.shm_nattch
is 2, we're still the first user this time, and we should executes line 123 to
line 129 of the codes above.

There is the following statement in `man shmget`:
       When a new shared memory segment is created, its contents are initialized to zero values
According to the statement above, dmix->shmptr->magic is 0 on shm first created.
So, to fix this issue, we should change the following line:
 122 	if (buf.shm_nattch == 1) {      /* we're the first user, clear the segment */
to:
 122 	if (dmix->shmptr->magic != SND_PCM_DIRECT_MAGIC) {      /* we're the first user, clear the segment */

Sincerely,
Sisrnb

 		 	   		  

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: A root cause of "unable to create IPC shm instance"
  2015-12-10 11:04 A root cause of "unable to create IPC shm instance" IceBsi
@ 2015-12-10 11:30 ` Jaroslav Kysela
  0 siblings, 0 replies; 2+ messages in thread
From: Jaroslav Kysela @ 2015-12-10 11:30 UTC (permalink / raw)
  To: alsa-devel; +Cc: IceBsi

Dne 10.12.2015 v 12:04 IceBsi napsal(a):
> Dear ALSA developers:
> 
> I found a root cause of the following issue by using strace:
>     unable to create IPC shm instance
> 
> Firstly, please see the test code below:
>   1 #include <stdio.h>
>   2 #include <unistd.h>
>   3 #include <sys/ipc.h>
>   4 #include <sys/shm.h>
>   5 #include <errno.h>
>   6 #include <string.h>
>   7 
>   8 int main(int argc, char *argv[])
>   9 {
>  10 	int r = 0;
>  11 	struct shmid_ds buf;
>  12 	key_t ipc_key = (key_t)325559;
>  13 	size_t shmsize = 488;
>  14 	int shmid = -1;
>  15 	mode_t ipc_perm = 0666;
>  16 	void *shmptr = NULL;
>  17 	pid_t pid;
>  18 
>  19 	printf("___%d:%d call shmget(%d,%u,%d)\n", __LINE__, getpid(), (int)(ipc_key), shmsize, IPC_CREAT | ipc_perm);
>  20 	shmid = shmget(ipc_key, shmsize, IPC_CREAT | ipc_perm);
>  21 	printf("___%d:%d ret shmget=%d\n", __LINE__, getpid(), shmid);
>  22 
>  23 	printf("___%d:%d call shmat(%d,0,0)\n", __LINE__, getpid(), shmid);
>  24 	shmptr = shmat(shmid, 0, 0);
>  25 	printf("___%d:%d ret shmat=%p\n", __LINE__, getpid(), shmptr);
>  26 
>  27 	printf("+++%d:%d call fork\n", __LINE__, getpid());
>  28 	pid = fork();
>  29 	printf("+++%d:%d ret fork=%d\n", __LINE__, getpid(), (int)pid);
>  30 
>  31 	printf("___%d:%d call shmctl(%d,IPC_STAT,%p)\n", __LINE__, getpid(), shmid, &buf);
>  32 	r = shmctl(shmid, IPC_STAT, &buf);
>  33 	printf("___%d:%d ret shmctl=%d\n", __LINE__, getpid(), r);
>  34 	printf("___%d:%d nattch=%lu\n", __LINE__, getpid(), buf.shm_nattch);
>  35 
>  36 	printf("___%d:%d call shmdt(%p)\n", __LINE__, getpid(), shmptr);
>  37 	r = shmdt(shmptr);
>  38 	printf("___%d:%d ret shmdt=%d\n", __LINE__, getpid(), r);
>  39 
>  40 	printf("___%d:%d call shmctl(%d,IPC_RMID,NULL)\n", __LINE__, getpid(), shmid);
>  41 	r = shmctl(shmid, IPC_RMID, NULL);
>  42 	printf("___%d:%d ret shmctl=%d, %s\n", __LINE__, getpid(), r, strerror(errno));
>  43 
>  44 	if ((pid_t)0 != pid) {
>  45 		printf("+++%d:%d call wait(NULL)\n", __LINE__, getpid());
>  46 		pid = wait(NULL);
>  47 		printf("+++%d:%d ret wait=%d\n", __LINE__, getpid(), (int)pid);
>  48 	}
>  49 
>  50 	return 0;
>  51 }
> The output of the test code is:
> ___19:11782 call shmget(325559,488,950)
> ___21:11782 ret shmget=2850820
> ___23:11782 call shmat(2850820,0,0)
> ___25:11782 ret shmat=0x7f452c223000
> +++27:11782 call fork
> +++29:11782 ret fork=11783
> ___31:11782 call shmctl(2850820,IPC_STAT,0x7fffdaf0a750)
> ___33:11782 ret shmctl=0
> ___34:11782 nattch=2
> ___36:11782 call shmdt(0x7f452c223000)
> +++29:11783 ret fork=0
> ___38:11782 ret shmdt=0
> ___40:11782 call shmctl(2850820,IPC_RMID,NULL)
> ___31:11783 call shmctl(2850820,IPC_STAT,0x7fffdaf0a750)
> ___42:11782 ret shmctl=0, Success
> +++45:11782 call wait(NULL)
> ___33:11783 ret shmctl=0
> ___34:11783 nattch=1
> ___36:11783 call shmdt(0x7f452c223000)
> ___38:11783 ret shmdt=0
> ___40:11783 call shmctl(2850820,IPC_RMID,NULL)
> ___42:11783 ret shmctl=-1, Invalid argument
> +++47:11782 ret wait=11783
> And sometimes output is:
> ___19:11798 call shmget(325559,488,950)
> ___21:11798 ret shmget=3112964
> ___23:11798 call shmat(3112964,0,0)
> ___25:11798 ret shmat=0x7f6b39378000
> +++27:11798 call fork
> +++29:11798 ret fork=11799
> ___31:11798 call shmctl(3112964,IPC_STAT,0x7fff3a6472a0)
> ___33:11798 ret shmctl=0
> +++29:11799 ret fork=0
> ___31:11799 call shmctl(3112964,IPC_STAT,0x7fff3a6472a0)
> ___34:11798 nattch=2
> ___36:11798 call shmdt(0x7f6b39378000)
> ___33:11799 ret shmctl=0
> ___38:11798 ret shmdt=0
> ___34:11799 nattch=2
> ___40:11798 call shmctl(3112964,IPC_RMID,NULL)
> ___36:11799 call shmdt(0x7f6b39378000)
> ___42:11798 ret shmctl=0, Success
> +++45:11798 call wait(NULL)
> ___38:11799 ret shmdt=0
> ___40:11799 call shmctl(3112964,IPC_RMID,NULL)
> ___42:11799 ret shmctl=-1, Invalid argument
> +++47:11798 ret wait=11799
>>From the outputs the parent process always get nattch=2, the child process
> get nattch=1 or sometimes get nattch=2.
> 
> Then please see the following lines of src/pcm/pcm_direct.c
> (from alsa-lib-1.1.0.tar.bz2):
>  110 	dmix->shmptr = shmat(dmix->shmid, 0, 0);
>  111 	if (dmix->shmptr == (void *) -1) {
>  112 		err = -errno;
>  113 		snd_pcm_direct_shm_discard(dmix);
>  114 		return err;
>  115 	}
>  116 	mlock(dmix->shmptr, sizeof(snd_pcm_direct_share_t));
>  117 	if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) {
>  118 		err = -errno;
>  119 		snd_pcm_direct_shm_discard(dmix);
>  120 		return err;
>  121 	}
>  122 	if (buf.shm_nattch == 1) {      /* we're the first user, clear the segment */
>  123 		memset(dmix->shmptr, 0, sizeof(snd_pcm_direct_share_t));
>  124 		if (dmix->ipc_gid>= 0) {
>  125 			buf.shm_perm.gid = dmix->ipc_gid;
>  126 			shmctl(dmix->shmid, IPC_SET, &buf);
>  127 		}
>  128 		dmix->shmptr->magic = SND_PCM_DIRECT_MAGIC;
>  129 		return 1;
>  130 	} else {
>  131 		if (dmix->shmptr->magic != SND_PCM_DIRECT_MAGIC) {
>  132 			snd_pcm_direct_shm_discard(dmix);
>  133 			return -EINVAL;
>  134 		}
>  135 	}
> If an applicatioin that uses alsa-lib invokes fork() and the fork() is invoked
> just after shmat(line 110) and just before shmctl(line 117), buf.shm_nattch
> will be 2, so "buf.shm_nattch == 1" will be false. But while buf.shm_nattch
> is 2, we're still the first user this time, and we should executes line 123 to
> line 129 of the codes above.
> 
> There is the following statement in `man shmget`:
>        When a new shared memory segment is created, its contents are initialized to zero values
> According to the statement above, dmix->shmptr->magic is 0 on shm first created.
> So, to fix this issue, we should change the following line:
>  122 	if (buf.shm_nattch == 1) {      /* we're the first user, clear the segment */
> to:
>  122 	if (dmix->shmptr->magic != SND_PCM_DIRECT_MAGIC) {      /* we're the first user, clear the segment */

You're talking about an application using threads ? Then a mutex should
be used here. Thanks for the analysis.

					Jaroslav

-- 
Jaroslav Kysela <perex@perex.cz>
Linux Sound Maintainer; ALSA Project; Red Hat, Inc.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-12-10 11:30 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-12-10 11:04 A root cause of "unable to create IPC shm instance" IceBsi
2015-12-10 11:30 ` Jaroslav Kysela

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.