All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jaroslav Kysela <perex@perex.cz>
To: alsa-devel@alsa-project.org
Cc: IceBsi <bsiice@msn.com>
Subject: Re: A root cause of "unable to create IPC shm instance"
Date: Thu, 10 Dec 2015 12:30:02 +0100	[thread overview]
Message-ID: <5669623A.3070208@perex.cz> (raw)
In-Reply-To: <COL125-W23C67B4D2A800D0EEC9E51D2E90@phx.gbl>

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.

      reply	other threads:[~2015-12-10 11:30 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-10 11:04 A root cause of "unable to create IPC shm instance" IceBsi
2015-12-10 11:30 ` Jaroslav Kysela [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5669623A.3070208@perex.cz \
    --to=perex@perex.cz \
    --cc=alsa-devel@alsa-project.org \
    --cc=bsiice@msn.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.