Hello Yubin, On 13 September 2017 at 10:34, Yubin Ruan <ablacktshirt@xxxxxxxxx> wrote: > On Tue, Sep 12, 2017 at 02:41:29PM +0200, Michael Kerrisk (man-pages) wrote: >> Hello Yubin, >> >> [...] >> > +.B PTHREAD_MUTEX_ROBUST >> > +can be set on a mutex attribute object so that when the owner of the mutex >> > +dies or when the process containing such a locked mutex performs >> > +.IR execve (2) >> > +, any future attempts to call >> > +.IR pthread_mutex_lock (3) >> > +on this mutex will suceed and return >> > +.B EOWNERDEAD >> > +to indicate that the original owner no longer exists and the mutex is left in >> > +an inconsistent state. >> How did you verify the point regarding execve(2)? I don't see this >> detailed mentioned in the standards or in the glibc source. > > Please see below the program I used to verify that. I haven't go into too much > detail in the POSIX standard, though. I think I must have read it at [1] or > somewhere else (don't remember...). Thanks for the details and example program. So, I see the kernel code that deals with this now: in fs/exec.c::exec_mmap(), there is a call to mm_release() which in turn calls exit_robust_list() So, this detail isn't in POSIX. I think what I will do is move discussion of that point into the NOTES. > And also, it is mentioned at [1] that when the process containing such a locked > mutex unmaps the memory containing the mutex, the mutex is unlocked... I think > this is trivial so I don't add it. It also appears not to be true on Linux, at least in some short tests I just did.[1] See my modified version of your program, below. Also when looking at the kernel code, I can see no call to mm_release() that would lead to this behavior. Cheers, Michael [1] And I wonder if the Solaris documentation is even correct, since, if we are talking about a shared anonymous mapping, the memory would not be released until *all* processes have unmapped the memory /************ verify-execve.c *****************/ #define _POSIX_C_SOURCE 200809L #define _GNU_SOURCE #include <errno.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ipc.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #define MEMSIZE 4096 #define ERROR_ON(func_name) \ fprintf(stderr, "error: " #func_name ": line[%d]: %s\n", __LINE__, strerror(errno)); int main(int argc, char *argv[]) { struct shm *shm = NULL; int ret_code = 0; pthread_mutex_t *mutexp = NULL; pthread_mutexattr_t attr; pid_t pid = 0; shm = mmap(NULL, MEMSIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED,-1, 0); if ((void *)-1 == shm) { ERROR_ON(shmat); return -1; } memset(shm, 0, sizeof(pthread_mutex_t)); printf("Successfully attached shared memory, trying to lock\n"); //initialize the lock mutexp = (pthread_mutex_t *)shm; pthread_mutexattr_init(&attr); pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST); pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(mutexp, &attr); pid = fork(); if (0 == pid) { sleep(1); printf("Child about to call pthread_mutex-Lock()\n"); ret_code = pthread_mutex_lock(mutexp); if (EOWNERDEAD == ret_code) { printf("child see EOWNERDEAD returned. Verification completed\n"); pthread_mutex_consistent(mutexp); pthread_mutex_unlock(mutexp); exit(0); } else { printf("child see [%d] returned\n", ret_code); exit(1); } } else { ret_code = pthread_mutex_lock(mutexp); if (0 == ret_code) { printf("parent successfully acquired the lock\n"); } else { ERROR_ON(pthread_mutex_lock); return -1; } printf("Parent sleeping 3 seconds\n"); sleep(3); if (munmap(shm, MEMSIZE) == -1) ERROR_ON(munmap); printf("Parent has unmapped the memory\n"); sleep(1); printf("Parent about to exit\n"); exit(0); /* printf("parent going to execve(/bin/true)\n"); execl("/bin/true", "true", (char *) NULL); */ } return 0; } -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html