1*49714e86SBryan Cantrill# 2*49714e86SBryan Cantrill# This file and its contents are supplied under the terms of the 3*49714e86SBryan Cantrill# Common Development and Distribution License ("CDDL"), version 1.0. 4*49714e86SBryan Cantrill# You may only use this file in accordance with the terms of version 5*49714e86SBryan Cantrill# 1.0 of the CDDL. 6*49714e86SBryan Cantrill# 7*49714e86SBryan Cantrill# A full copy of the text of the CDDL should have accompanied this 8*49714e86SBryan Cantrill# source. A copy of the CDDL is also available via the Internet at 9*49714e86SBryan Cantrill# http://www.illumos.org/license/CDDL. 10*49714e86SBryan Cantrill# 11*49714e86SBryan Cantrill 12*49714e86SBryan Cantrill# 13*49714e86SBryan Cantrill# Copyright (c) 2017, Joyent, Inc. All rights reserved. 14*49714e86SBryan Cantrill# 15*49714e86SBryan Cantrill 16*49714e86SBryan Cantrill# 17*49714e86SBryan Cantrill# This test attempts to reproduce a three-way deadlock between mod_lock, 18*49714e86SBryan Cantrill# dtrace_lock and P_PR_LOCK that is induced by shmsys having to go through 19*49714e86SBryan Cantrill# mod_hold_stub. 20*49714e86SBryan Cantrill# 21*49714e86SBryan Cantrillif [ $# != 1 ]; then 22*49714e86SBryan Cantrill echo expected one argument: '<'dtrace-path'>' 23*49714e86SBryan Cantrill exit 2 24*49714e86SBryan Cantrillfi 25*49714e86SBryan Cantrill 26*49714e86SBryan Cantrilldtrace=$1 27*49714e86SBryan CantrillDIR=/var/tmp/dtest.$$ 28*49714e86SBryan Cantrill 29*49714e86SBryan Cantrillmkdir $DIR 30*49714e86SBryan Cantrillcd $DIR 31*49714e86SBryan Cantrill 32*49714e86SBryan Cantrillcat > prov.d <<EOF 33*49714e86SBryan Cantrillprovider test_prov { 34*49714e86SBryan Cantrill probe ripraf(); 35*49714e86SBryan Cantrill}; 36*49714e86SBryan CantrillEOF 37*49714e86SBryan Cantrill 38*49714e86SBryan Cantrill$dtrace -h -s prov.d 39*49714e86SBryan Cantrillif [ $? -ne 0 ]; then 40*49714e86SBryan Cantrill print -u2 "failed to generate header file" 41*49714e86SBryan Cantrill exit 1 42*49714e86SBryan Cantrillfi 43*49714e86SBryan Cantrill 44*49714e86SBryan Cantrillcat > test.c <<EOF 45*49714e86SBryan Cantrill#include <unistd.h> 46*49714e86SBryan Cantrill#include <stdlib.h> 47*49714e86SBryan Cantrill#include <sys/types.h> 48*49714e86SBryan Cantrill#include <sys/ipc.h> 49*49714e86SBryan Cantrill#include <sys/shm.h> 50*49714e86SBryan Cantrill#include <stdio.h> 51*49714e86SBryan Cantrill#include <stdlib.h> 52*49714e86SBryan Cantrill#include "prov.h" 53*49714e86SBryan Cantrill 54*49714e86SBryan Cantrillvoid 55*49714e86SBryan Cantrillmain(int argc) 56*49714e86SBryan Cantrill{ 57*49714e86SBryan Cantrill void *addr; 58*49714e86SBryan Cantrill int shmid; 59*49714e86SBryan Cantrill 60*49714e86SBryan Cantrill if (argc > 1) { 61*49714e86SBryan Cantrill TEST_PROV_RIPRAF(); 62*49714e86SBryan Cantrill exit(0); 63*49714e86SBryan Cantrill } 64*49714e86SBryan Cantrill 65*49714e86SBryan Cantrill shmid = shmget(IPC_PRIVATE, sizeof (int), IPC_CREAT | 0666); 66*49714e86SBryan Cantrill 67*49714e86SBryan Cantrill if (shmid == -1) { 68*49714e86SBryan Cantrill perror("shmget: "); 69*49714e86SBryan Cantrill exit(1); 70*49714e86SBryan Cantrill } 71*49714e86SBryan Cantrill 72*49714e86SBryan Cantrill if ((addr = shmat(shmid, NULL, 0)) == (void *)-1) { 73*49714e86SBryan Cantrill perror("shmat: "); 74*49714e86SBryan Cantrill exit(1); 75*49714e86SBryan Cantrill } 76*49714e86SBryan Cantrill 77*49714e86SBryan Cantrill printf("%p\n", addr); 78*49714e86SBryan Cantrill 79*49714e86SBryan Cantrill for (;;) { 80*49714e86SBryan Cantrill TEST_PROV_RIPRAF(); 81*49714e86SBryan Cantrill sleep(1); 82*49714e86SBryan Cantrill } 83*49714e86SBryan Cantrill} 84*49714e86SBryan CantrillEOF 85*49714e86SBryan Cantrill 86*49714e86SBryan Cantrillgcc -m32 -c test.c 87*49714e86SBryan Cantrillif [ $? -ne 0 ]; then 88*49714e86SBryan Cantrill print -u2 "failed to compile test.c" 89*49714e86SBryan Cantrill exit 1 90*49714e86SBryan Cantrillfi 91*49714e86SBryan Cantrill 92*49714e86SBryan Cantrill$dtrace -G -32 -s prov.d test.o 93*49714e86SBryan Cantrill 94*49714e86SBryan Cantrillif [ $? -ne 0 ]; then 95*49714e86SBryan Cantrill print -u2 "failed to create DOF" 96*49714e86SBryan Cantrill exit 1 97*49714e86SBryan Cantrillfi 98*49714e86SBryan Cantrill 99*49714e86SBryan Cantrillgcc -m32 -o test test.o prov.o 100*49714e86SBryan Cantrill 101*49714e86SBryan Cantrillif [ $? -ne 0 ]; then 102*49714e86SBryan Cantrill print -u2 "failed to link final executable" 103*49714e86SBryan Cantrill exit 1 104*49714e86SBryan Cantrillfi 105*49714e86SBryan Cantrill 106*49714e86SBryan Cantrill# 107*49714e86SBryan Cantrill# Kick off the victim program. 108*49714e86SBryan Cantrill# 109*49714e86SBryan Cantrill./test & 110*49714e86SBryan Cantrill 111*49714e86SBryan Cantrillvictim=$! 112*49714e86SBryan Cantrill 113*49714e86SBryan Cantrill# 114*49714e86SBryan Cantrill# Kick off a shell that will do nothing but read our victim's /proc map 115*49714e86SBryan Cantrill# 116*49714e86SBryan Cantrill( while true ; do read foo < /proc/$victim/map ; done ) & 117*49714e86SBryan Cantrillstubby=$! 118*49714e86SBryan Cantrill 119*49714e86SBryan Cantrill# 120*49714e86SBryan Cantrill# Kick off a shell that will do nothing but instrument (and de-instrument) 121*49714e86SBryan Cantrill# the victim 122*49714e86SBryan Cantrill# 123*49714e86SBryan Cantrill( while true; do \ 124*49714e86SBryan Cantrill $dtrace -q -P test_prov$victim -n BEGIN'{exit(0)}' > /dev/null ; done ) & 125*49714e86SBryan Cantrillinst=$! 126*49714e86SBryan Cantrill 127*49714e86SBryan Cantrill# 128*49714e86SBryan Cantrill# Finally, kick off a shell that will cause lots of provider registration and 129*49714e86SBryan Cantrill# (importantly) de-registration 130*49714e86SBryan Cantrill# 131*49714e86SBryan Cantrill( while true; do ./test foo ; done) & 132*49714e86SBryan Cantrillreg=$! 133*49714e86SBryan Cantrill 134*49714e86SBryan Cantrillecho $DIR 135*49714e86SBryan Cantrillecho victim: $victim 136*49714e86SBryan Cantrillecho stubby: $stubby 137*49714e86SBryan Cantrillecho inst: $inst 138*49714e86SBryan Cantrillecho reg: $reg 139*49714e86SBryan Cantrill 140*49714e86SBryan Cantrillsleep 120 141*49714e86SBryan Cantrill 142*49714e86SBryan Cantrillkill $reg 143*49714e86SBryan Cantrillsleep 1 144*49714e86SBryan Cantrillkill $inst 145*49714e86SBryan Cantrillsleep 1 146*49714e86SBryan Cantrillkill $stubby 147*49714e86SBryan Cantrillsleep 1 148*49714e86SBryan Cantrillkill $victim 149*49714e86SBryan Cantrill 150*49714e86SBryan Cantrill# 151*49714e86SBryan Cantrill# If we're deadlocked, this DTrace enabling won't work (if we even make it this 152*49714e86SBryan Cantrill# far, which seems unlikely). In the spirit of the deadlock, we denote our 153*49714e86SBryan Cantrill# success by emiting a classic Faulknerism. 154*49714e86SBryan Cantrill# 155*49714e86SBryan Cantrillraf="Maybe you're not so worthless!" 156*49714e86SBryan Cantrilldtrace -qn BEGIN"{printf(\"$raf\"); exit(0)}" 157*49714e86SBryan Cantrill 158*49714e86SBryan Cantrillcd / 159*49714e86SBryan Cantrill/usr/bin/rm -rf $DIR 160*49714e86SBryan Cantrill 161*49714e86SBryan Cantrillexit 0 162