t_getenv_thread.c revision 272343
190075Sobrien/* $NetBSD: t_getenv_thread.c,v 1.2 2012/03/15 02:02:23 joerg Exp $ */ 290075Sobrien 390075Sobrien/*- 490075Sobrien * Copyright (c) 2010 The NetBSD Foundation, Inc. 590075Sobrien * All rights reserved. 690075Sobrien * 790075Sobrien * This code is derived from software contributed to The NetBSD Foundation 890075Sobrien * by Matthias Scheler. 990075Sobrien * 1090075Sobrien * Redistribution and use in source and binary forms, with or without 1190075Sobrien * modification, are permitted provided that the following conditions 1290075Sobrien * are met: 1390075Sobrien * 1. Redistributions of source code must retain the above copyright 1490075Sobrien * notice, this list of conditions and the following disclaimer. 1590075Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1690075Sobrien * notice, this list of conditions and the following disclaimer in the 1790075Sobrien * documentation and/or other materials provided with the distribution. 1890075Sobrien * 1990075Sobrien * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2090075Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2190075Sobrien * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2290075Sobrien * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2390075Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2490075Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2590075Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2690075Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2790075Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2890075Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2990075Sobrien * POSSIBILITY OF SUCH DAMAGE. 3090075Sobrien */ 3190075Sobrien#include <sys/cdefs.h> 3290075Sobrien__RCSID("$NetBSD: t_getenv_thread.c,v 1.2 2012/03/15 02:02:23 joerg Exp $"); 3390075Sobrien 3490075Sobrien#include <atf-c.h> 3590075Sobrien#include <errno.h> 3690075Sobrien#include <pthread.h> 3790075Sobrien#include <stdio.h> 3890075Sobrien#include <stdlib.h> 3990075Sobrien#include <string.h> 4090075Sobrien#include <time.h> 4190075Sobrien 4290075Sobrien#define THREADED_NUM_THREADS 8 4390075Sobrien#define THREADED_NUM_VARS 16 4490075Sobrien#define THREADED_VAR_NAME "THREADED%zu" 4590075Sobrien#define THREADED_RUN_TIME 10 4690075Sobrien 4790075Sobrienstatic void *thread_getenv_r(void *); 4890075Sobrienstatic void *thread_putenv(void *); 4990075Sobrienstatic void *thread_setenv(void *); 5090075Sobrienstatic void *thread_unsetenv(void *); 5190075Sobrien 5290075Sobrienstatic void * 5390075Sobrienthread_getenv_r(void *arg) 5490075Sobrien{ 5590075Sobrien time_t endtime; 5690075Sobrien 5790075Sobrien endtime = *(time_t *)arg; 5890075Sobrien do { 5990075Sobrien size_t i; 6090075Sobrien char name[32], value[128]; 6190075Sobrien 6290075Sobrien i = lrand48() % THREADED_NUM_VARS; 6390075Sobrien (void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i); 6490075Sobrien 6590075Sobrien if (getenv_r(name, value, sizeof(value)) == -1) { 6690075Sobrien ATF_CHECK(errno == ENOENT); 6790075Sobrien } 6890075Sobrien } while (time(NULL) < endtime); 6990075Sobrien 7090075Sobrien return NULL; 7190075Sobrien} 7290075Sobrien 7390075Sobrien 7490075Sobrienstatic void * 7590075Sobrienthread_putenv(void *arg) 7690075Sobrien{ 7790075Sobrien time_t endtime; 7890075Sobrien size_t i; 7990075Sobrien static char vars[THREADED_NUM_VARS][128]; 8090075Sobrien 8190075Sobrien for (i = 0; i < THREADED_NUM_VARS; i++) { 8290075Sobrien (void)snprintf(vars[i], sizeof(vars[i]), 8390075Sobrien THREADED_VAR_NAME "=putenv %ld", i, lrand48()); 8490075Sobrien } 8590075Sobrien 8690075Sobrien endtime = *(time_t *)arg; 8790075Sobrien do { 8890075Sobrien char name[128]; 8990075Sobrien 9090075Sobrien i = lrand48() % THREADED_NUM_VARS; 9190075Sobrien (void)strlcpy(name, vars[i], sizeof(name)); 9290075Sobrien *strchr(name, '=') = '\0'; 9390075Sobrien 9490075Sobrien ATF_CHECK(unsetenv(name) != -1); 9590075Sobrien ATF_CHECK(putenv(vars[i]) != -1); 9690075Sobrien } while (time(NULL) < endtime); 9790075Sobrien 9890075Sobrien return NULL; 9990075Sobrien} 10090075Sobrien 10190075Sobrienstatic void * 10290075Sobrienthread_setenv(void *arg) 10390075Sobrien{ 10490075Sobrien time_t endtime; 10590075Sobrien 10690075Sobrien endtime = *(time_t *)arg; 10790075Sobrien do { 10890075Sobrien size_t i; 10990075Sobrien char name[32], value[64]; 11090075Sobrien 11190075Sobrien i = lrand48() % THREADED_NUM_VARS; 11290075Sobrien (void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i); 11390075Sobrien (void)snprintf(value, sizeof(value), "setenv %ld", lrand48()); 11490075Sobrien 11590075Sobrien ATF_CHECK(setenv(name, value, 1) != -1); 11690075Sobrien } while (time(NULL) < endtime); 11790075Sobrien 11890075Sobrien return NULL; 11990075Sobrien} 12090075Sobrien 12190075Sobrienstatic void * 12290075Sobrienthread_unsetenv(void *arg) 12390075Sobrien{ 12490075Sobrien time_t endtime; 12590075Sobrien 12690075Sobrien endtime = *(time_t *)arg; 12790075Sobrien do { 12890075Sobrien size_t i; 12990075Sobrien char name[32]; 13090075Sobrien 13190075Sobrien i = lrand48() % THREADED_NUM_VARS; 13290075Sobrien (void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i); 13390075Sobrien 13490075Sobrien ATF_CHECK(unsetenv(name) != -1); 13590075Sobrien } while (time(NULL) < endtime); 13690075Sobrien 13790075Sobrien return NULL; 13890075Sobrien} 13990075Sobrien 14090075SobrienATF_TC(getenv_r_thread); 14190075SobrienATF_TC_HEAD(getenv_r_thread, tc) 14290075Sobrien{ 14390075Sobrien 14490075Sobrien atf_tc_set_md_var(tc, "descr", "Test getenv_r(3) with threads"); 14590075Sobrien atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5); 14690075Sobrien} 14790075Sobrien 14890075SobrienATF_TC_BODY(getenv_r_thread, tc) 14990075Sobrien{ 15090075Sobrien pthread_t threads[THREADED_NUM_THREADS]; 15190075Sobrien time_t endtime; 15290075Sobrien size_t i, j; 15390075Sobrien 15490075Sobrien endtime = time(NULL) + THREADED_RUN_TIME; 15590075Sobrien 15690075Sobrien for (i = j = 0; j < 2; j++) { 15790075Sobrien 15890075Sobrien ATF_CHECK(pthread_create(&threads[i++], NULL, thread_getenv_r, 15990075Sobrien &endtime) == 0); 16090075Sobrien } 16190075Sobrien 16290075Sobrien for (j = 0; j < i; j++) 16390075Sobrien ATF_CHECK(pthread_join(threads[j], NULL) == 0); 16490075Sobrien} 16590075Sobrien 16690075SobrienATF_TC(putenv_thread); 16790075SobrienATF_TC_HEAD(putenv_thread, tc) 16890075Sobrien{ 16990075Sobrien atf_tc_set_md_var(tc, "descr", "Test concurrent access by putenv(3)"); 17090075Sobrien atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5); 17190075Sobrien} 17290075Sobrien 17390075SobrienATF_TC_BODY(putenv_thread, tc) 17490075Sobrien{ 17590075Sobrien pthread_t threads[THREADED_NUM_THREADS]; 17690075Sobrien time_t endtime; 17790075Sobrien size_t i, j; 17890075Sobrien 17990075Sobrien endtime = time(NULL) + THREADED_RUN_TIME; 18090075Sobrien 18190075Sobrien for (i = j = 0; j < 2; j++) { 18290075Sobrien 18390075Sobrien ATF_CHECK(pthread_create(&threads[i++], NULL, thread_putenv, 18490075Sobrien &endtime) == 0); 18590075Sobrien } 18690075Sobrien 18790075Sobrien for (j = 0; j < i; j++) 18890075Sobrien ATF_CHECK(pthread_join(threads[j], NULL) == 0); 18990075Sobrien} 19090075Sobrien 19190075SobrienATF_TC(setenv_thread); 19290075SobrienATF_TC_HEAD(setenv_thread, tc) 19390075Sobrien{ 19490075Sobrien atf_tc_set_md_var(tc, "descr", "Test concurrent access by setenv(3)"); 19590075Sobrien atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5); 19690075Sobrien} 19790075Sobrien 19890075SobrienATF_TC_BODY(setenv_thread, tc) 19990075Sobrien{ 20090075Sobrien pthread_t threads[THREADED_NUM_THREADS]; 20190075Sobrien time_t endtime; 20290075Sobrien size_t i, j; 20390075Sobrien 20490075Sobrien endtime = time(NULL) + THREADED_RUN_TIME; 20590075Sobrien 20690075Sobrien for (i = j = 0; j < 2; j++) { 20790075Sobrien 20890075Sobrien ATF_CHECK(pthread_create(&threads[i++], NULL, thread_setenv, 20990075Sobrien &endtime) == 0); 21090075Sobrien } 21190075Sobrien 21290075Sobrien for (j = 0; j < i; j++) 21390075Sobrien ATF_CHECK(pthread_join(threads[j], NULL) == 0); 21490075Sobrien} 21590075Sobrien 21690075SobrienATF_TC(unsetenv_thread); 21790075SobrienATF_TC_HEAD(unsetenv_thread, tc) 21890075Sobrien{ 21990075Sobrien atf_tc_set_md_var(tc, "descr", "Test unsetenv(3) with threads"); 22090075Sobrien atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5); 22190075Sobrien} 22290075Sobrien 22390075SobrienATF_TC_BODY(unsetenv_thread, tc) 22490075Sobrien{ 22590075Sobrien pthread_t threads[THREADED_NUM_THREADS]; 22690075Sobrien time_t endtime; 22790075Sobrien size_t i, j; 22890075Sobrien 22990075Sobrien endtime = time(NULL) + THREADED_RUN_TIME; 23090075Sobrien 23190075Sobrien for (i = j = 0; j < 2; j++) { 23290075Sobrien 23390075Sobrien ATF_CHECK(pthread_create(&threads[i++], NULL, thread_unsetenv, 23490075Sobrien &endtime) == 0); 23590075Sobrien } 23690075Sobrien 23790075Sobrien for (j = 0; j < i; j++) 23890075Sobrien ATF_CHECK(pthread_join(threads[j], NULL) == 0); 23990075Sobrien} 24090075Sobrien 24190075SobrienATF_TP_ADD_TCS(tp) 24290075Sobrien{ 24390075Sobrien 24490075Sobrien ATF_TP_ADD_TC(tp, getenv_r_thread); 24590075Sobrien ATF_TP_ADD_TC(tp, putenv_thread); 24690075Sobrien ATF_TP_ADD_TC(tp, setenv_thread); 24790075Sobrien ATF_TP_ADD_TC(tp, unsetenv_thread); 24890075Sobrien 24990075Sobrien return atf_no_error(); 25090075Sobrien} 25190075Sobrien