Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 1451011 Details for
Bug 1401665
Fix process shared robust mutex defects.
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
Test Code v3
test-robust-mutex.c (text/x-csrc), 7.13 KB, created by
Carlos O'Donell
on 2018-06-13 19:45:36 UTC
(
hide
)
Description:
Test Code v3
Filename:
MIME Type:
Creator:
Carlos O'Donell
Created:
2018-06-13 19:45:36 UTC
Size:
7.13 KB
patch
obsolete
>/* > Robust mutex test > > Copyright (C) Amitay Isaacs 2016 > > This program is free software; you can redistribute it and/or modify > it under the terms of the GNU General Public License as published by > the Free Software Foundation; either version 3 of the License, or > (at your option) any later version. > > This program is distributed in the hope that it will be useful, > but WITHOUT ANY WARRANTY; without even the implied warranty of > MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > GNU General Public License for more details. > > You should have received a copy of the GNU General Public License > along with this program; if not, see <http://www.gnu.org/licenses/>. >*/ > >/* > * Run this test as follows: > * > * 0. Start initializer for shared memory. > * > * $ ./bin/test_mutex_raw /tmp/foo init > * > * 1. Running all processes at normal priority > * > * $ while true ; do ./bin/test_mutex_raw /tmp/foo 10 0 ; done > * > * 2. Running all processes at real-time priority (as root) > * > * # while true ; do ./bin/test_mutex_raw /tmp/foo 10 1 ; done > * > * The test will block after few iterations. At this time none of the > * child processes is holding the mutex. > * > * To check which process is holding a lock: > * > * $ ./bin/test_mutex_raw /tmp/foo debug > * > * If no pid is printed, then no process is holding the mutex. > */ > >#define _GNU_SOURCE >#include <stdio.h> >#include <unistd.h> >#include <inttypes.h> >#include <sys/types.h> >#include <sys/fcntl.h> >#include <stdlib.h> >#include <string.h> >#include <sys/wait.h> >#include <sched.h> >#include <sys/mman.h> >#include <pthread.h> >#include <errno.h> >#include <stdbool.h> > >static void set_realtime(void) >{ > struct sched_param p; > int ret; > > p.sched_priority = 1; > > ret = sched_setscheduler(0, SCHED_FIFO, &p); > if (ret == -1) { > fprintf(stderr, "Failed to set scheduler to SCHED_FIFO\n"); > } >} > >static void high_priority(void) >{ > int ret; > > ret = nice(-20); > if (ret == -1) { > fprintf(stderr, "Failed to set high priority\n"); > } >} > >static void run_child(const char *filename) >{ > pthread_mutex_t *mutex; > void *addr; > int ret, fd; > > fd = open(filename, O_RDWR, 0600); > if (fd == -1) { > exit(1); > } > > addr = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, > MAP_SHARED|MAP_FILE, fd, 0); > if (addr == NULL) { > exit(2); > } > > mutex = (pthread_mutex_t *)addr; > > /* Every process will lock once, and die once. */ > fprintf(stderr, "pid %u locking\n", getpid()); > do > { > ret = pthread_mutex_lock(mutex); > > /* fprintf(stderr, "pid %u lock attempt, ret=%d\n", getpid(), ret); */ > > if (ret == EOWNERDEAD) > { > if (pthread_mutex_consistent (mutex) == 0) { > pthread_mutex_unlock(mutex); > } else { > fprintf(stderr, "pthread_mutex_consistent failed\n"); > exit (1); > } > /* fprintf(stderr, "pid %u recovery lock attempt, ret=%d\n", getpid(), ret); */ > /* Will loop and try to lock again. */ > } > > } while (ret != 0); > > fprintf (stderr, "pid %u locked, now killing\n", getpid()); > kill(getpid(), SIGKILL); >} > >#define PRIO_NORMAL 0 >#define PRIO_REALTIME 1 >#define PRIO_NICE_20 2 > >int main(int argc, const char **argv) >{ > pthread_mutexattr_t ma; > pthread_mutex_t *mutex; > int fd, ret, i; > pid_t pid; > void *addr; > int num_children; > int priority = PRIO_NORMAL; > > if (argc < 3 || argc > 4) { > fprintf(stderr, "Usage: %s <file> <n> [0|1|2]\n", argv[0]); > fprintf(stderr, " %s <file> debug\n", argv[0]); > exit(1); > } > > if (argc == 4) { > priority = atoi(argv[3]); > } > > if (priority == PRIO_REALTIME) { > set_realtime(); > } else if (priority == PRIO_NICE_20) { > high_priority(); > } > > fd = open(argv[1], O_CREAT|O_RDWR, 0600); > if (fd == -1) { > fprintf(stderr, "open failed\n"); > exit(1); > } > > ret = lseek(fd, 0, SEEK_SET); > if (ret != 0) { > fprintf(stderr, "lseek failed\n"); > exit(1); > } > > /* Truncate the file backing the mutex only in the init phase. */ > if (strcmp(argv[2], "init") == 0) { > ret = ftruncate(fd, sizeof(pthread_mutex_t)); > if (ret != 0) { > fprintf(stderr, "ftruncate failed\n"); > exit(1); > } > } > > addr = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, > MAP_SHARED|MAP_FILE, fd, 0); > if (addr == NULL) { > fprintf(stderr, "mmap failed\n"); > exit(1); > } > > mutex = (pthread_mutex_t *)addr; > > if (strcmp(argv[2], "debug") == 0) { > ret = pthread_mutex_trylock(mutex); > if (ret == EOWNERDEAD) { > ret = pthread_mutex_consistent(mutex); > if (ret == 0) { > pthread_mutex_unlock(mutex); > } else { > fprintf(stderr, "pthread_mutex_consistent failed\n"); > exit (1); > } > } else if (ret == EBUSY) { > printf("pid=%u\n", mutex->__data.__owner); > } else if (ret == 0) { > pthread_mutex_unlock(mutex); > } > exit(0); > } > > /* Only the initializing process does initialization because it is > undefined behaviour to re-initialize an already initialized mutex > that was not destroyed. */ > if (strcmp(argv[2], "init") == 0) { > > ret = pthread_mutexattr_init(&ma); > if (ret != 0) { > fprintf(stderr, "pthread_mutexattr_init failed\n"); > exit(1); > } > > ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); > if (ret != 0) { > fprintf(stderr, "pthread_mutexattr_settype failed\n"); > exit(1); > } > > ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); > if (ret != 0) { > fprintf(stderr, "pthread_mutexattr_setpshared failed\n"); > exit(1); > } > > ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); > if (ret != 0) { > fprintf(stderr, "pthread_mutexattr_setrobust failed\n"); > exit(1); > } > > ret = pthread_mutex_init(mutex, &ma); > if (ret != 0) { > fprintf(stderr, "pthread_mutex_init failed\n"); > exit(1); > } > > for (;;) > sleep (10); > } > > /* Acquire the mutext for the first time. Might be dead. > Might also be concurrent with the high-priority threads. */ > fprintf (stderr, "main: Acquire mutex.\n"); > do { > ret = pthread_mutex_lock(mutex); > > /* Not consistent? Try to make it so. */ > if (ret == EOWNERDEAD) > { > if (pthread_mutex_consistent(mutex) == 0) > { > pthread_mutex_unlock (mutex); > } else { > fprintf(stderr, "pthread_mutex_consistent failed\n"); > exit (1); > } > > /* Will loop and try to lock again. */ > fprintf (stderr, "main: Unlock recovery ret = %d\n", ret); > } > > } while (ret != 0); > > setpgid(0, 0); > > fprintf(stderr, "Creating children\n"); > num_children = atoi(argv[2]); > > for (i=0; i<num_children; i++) { > pid = fork(); > if (pid < 0) { > fprintf(stderr, "fork() failed\n"); > exit(1); > } > if (pid == 0) { > close(fd); > run_child(argv[1]); > exit(1); > } > } > > fprintf(stderr, "Waiting for children\n"); > > /* Unlock the recently acquired mutex or the old lost mutex. */ > ret = pthread_mutex_unlock(mutex); > if (ret != 0) { > fprintf(stderr, "pthread_mutex_unlock failed\n"); > exit(1); > } > > /* All threads are running now, and each will take the lock and > die in turn. When they are all dead we will exit and be started > again. */ > for (i=0; i<num_children; i++) { > int status; > > pid = waitpid(-1, &status, 0); > if (pid <= 0) { > fprintf(stderr, "waitpid() failed\n"); > } > fprintf (stderr, "Reaped %u\n", (unsigned int) pid); > } > > close(fd); > > /* We never unlink the file, but we might at some point, so this > is just a reminder. */ > if (strcmp(argv[2], "init") == 0) { > unlink(argv[1]); > } > > exit(0); >} >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 1401665
:
1228146
|
1232820
| 1451011 |
1479264