1#!/bin/sh 2 3# 4# Copyright (c) 2013 EMC Corp. 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# Regression test for kern/150138: signal sent to stopped, traced process 30# not immediately handled on continue. 31# Fixed in r212047. 32 33# Test scenario by Dan McNulty <dkmcnulty gmail.com> 34 35. ../default.cfg 36 37here=`pwd` 38wd=/tmp/signal.dir 39rm -rf $wd 40mkdir -p $wd 41cd $wd 42cat > waitthread.c <<EOF 43#include <unistd.h> 44#include <stdlib.h> 45#include <pthread.h> 46#include <stdio.h> 47#include <assert.h> 48#include <signal.h> 49#include <time.h> 50#include <sys/syscall.h> 51#include <string.h> 52#include <fcntl.h> 53#include <sys/types.h> 54#include <sys/stat.h> 55#include <errno.h> 56 57struct threadArg { 58 int id; 59 pthread_mutex_t *mutex; 60}; 61 62void *entry(void *arg) { 63 struct threadArg *thisArg = (struct threadArg *)arg; 64 65 long lwp_id = thisArg->id; 66 if( syscall(SYS_thr_self, &lwp_id) ) { 67 perror("syscall"); 68 } 69 70 printf("%ld waiting on lock\n", lwp_id); 71 72 if( pthread_mutex_lock(thisArg->mutex) != 0 ) { 73 perror("pthread_mutex_lock"); 74 return NULL; 75 } 76 77 printf("%ld obtained lock\n", lwp_id); 78 79 if( pthread_mutex_unlock(thisArg->mutex) != 0 ) { 80 perror("pthread_mutex_unlock"); 81 return NULL; 82 } 83 84 printf("%ld released lock\n", lwp_id); 85 86 return NULL; 87} 88 89int main(int argc, char **argv) { 90 if( 2 != argc ) { 91 printf("Usage: %s <num. of threads>\n", argv[0]); 92 return EXIT_FAILURE; 93 } 94 95 printf("%d\n", getpid()); 96 97 int numThreads; 98 sscanf(argv[1], "%d", &numThreads); 99 if( numThreads < 1 ) numThreads = 1; 100 101 pthread_t *threads = (pthread_t *)malloc(sizeof(pthread_t)*numThreads); 102 103 pthread_mutex_t *mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); 104 105 if( pthread_mutex_init(mutex, NULL) != 0 ) { 106 perror("pthread_mutex_init"); 107 return EXIT_FAILURE; 108 } 109 110 if( pthread_mutex_lock(mutex) != 0 ) { 111 perror("pthread_mutex_lock"); 112 return EXIT_FAILURE; 113 } 114 115 int i; 116 for(i = 0; i < numThreads; ++i) { 117 struct threadArg *arg = (struct threadArg *)malloc(sizeof(struct threadArg)); 118 arg->id = i; 119 arg->mutex = mutex; 120 assert( !pthread_create(&threads[i], NULL, &entry, (void *)arg) ); 121 } 122 123 // Wait on the named pipe 124 unlink("/tmp/waitthread"); 125 if( mkfifo("/tmp/waitthread", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) ) { 126 perror("mkfifo"); 127 return EXIT_FAILURE; 128 } 129 130 FILE *fifo; 131 do { 132 if( (fifo = fopen("/tmp/waitthread", "r")) == NULL ) { 133 if( errno == EINTR ) continue; 134 135 perror("fopen"); 136 return EXIT_FAILURE; 137 } 138 break; 139 }while(1); 140 141 unsigned char byte; 142 if( fread(&byte, sizeof(unsigned char), 1, fifo) != 1 ) { 143 perror("fread"); 144 } 145 146 fclose(fifo); 147 148 unlink("/tmp/waitthread"); 149 150 printf("Received notification\n"); 151 152 if( pthread_mutex_unlock(mutex) != 0 ) { 153 perror("pthread_mutex_unlock"); 154 return EXIT_FAILURE; 155 } 156 157 printf("Unlocked mutex, joining\n"); 158 159 for(i = 0; i < numThreads; ++i ) { 160 assert( !pthread_join(threads[i], NULL) ); 161 } 162 163 return EXIT_SUCCESS; 164} 165EOF 166cat > tkill.c <<EOF 167#include <sys/syscall.h> 168#include <unistd.h> 169#include <stdio.h> 170#include <errno.h> 171#include <stdlib.h> 172#include <signal.h> 173 174int main(int argc, char *argv[]) { 175 if( argc != 4 ) { 176 printf("Usage: %s <pid> <lwp_id> <sig>\n", argv[0]); 177 return EXIT_FAILURE; 178 } 179 180 pid_t pid; 181 sscanf(argv[1], "%d", &pid); 182 183 long id; 184 sscanf(argv[2], "%ld", &id); 185 186 int sig; 187 sscanf(argv[3], "%d", &sig); 188 189 if( syscall(SYS_thr_kill2, pid, id, sig) ) { 190 perror("syscall"); 191 } 192 193 return EXIT_SUCCESS; 194} 195EOF 196mycc -o waitthread -Wall -Wextra waitthread.c -lpthread || exit 197mycc -o tkill -Wall -Wextra tkill.c || exit 198rm -f waitthread.c tkill.c 199 200rm -f gdbfifo gdbout pstat /tmp/waitthread 201pkill -9 waitthread 202pgrep -q waitthread && { pgrep waitthread | xargs ps -lHp; exit 1; } 203mkfifo gdbfifo 204trap "rm -f gdbfifo" EXIT INT 205sleep 300 > gdbfifo & # Keep the fifo open 206sleep .5 207fifopid=$! 208 209(trap - INT; gdb ./waitthread < gdbfifo > gdbout 2>&1) & 210sleep .8 211gdbpid=$! 212echo "set args 8" > gdbfifo 213echo "run" > gdbfifo 214sleep .8 215 216for i in `jot 5`; do 217 pid=`ps -x | grep -v grep | grep "waitthread 8" | 218 sed 's/^ *//;s/ .*//'` 219 [ -n "$pid" ] && break 220 sleep 1 221done 222s=0 223if [ -n "$pid" ]; then 224 procstat -t $pid > pstat 225 226 t1=`grep fifo pstat | awk '{print $2}'` 227 t2=`grep umtxn pstat | awk '{print $2}' | tail -1` 228 229 set -e 230 ./tkill $pid $t1 5 # SIGTRAP 231 ./tkill $pid $t2 2 # SIGINT 232 set +e 233 234 echo "c" > gdbfifo 235 echo "quit" > gdbfifo 236 sleep 1 237 grep -q "signal SIGINT" gdbout || { echo FAIL; cat gdbout; s=1; } 238else 239 echo "Did not find pid for test program waitthread" 240 s=2 241fi 242 243kill -9 $fifopid $gdbpid > /dev/null 2>&1 244pgrep -q waitthread && pkill -9 waitthread 245cd $here 246rm -rf $wd /tmp/waitthread 247exit $s 248