165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes/* 265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * Copyright (C) 2014 The Android Open Source Project 365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * 465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * you may not use this file except in compliance with the License. 665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * You may obtain a copy of the License at 765f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * 865f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 965f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * 1065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * Unless required by applicable law or agreed to in writing, software 1165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 1265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * See the License for the specific language governing permissions and 1465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * limitations under the License. 1565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes */ 1665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 17f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui#include <pty.h> 18f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui 1965f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes#include <gtest/gtest.h> 2065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 21f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui#include <pthread.h> 2265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes#include <sys/ioctl.h> 2365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 24f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui#include <atomic> 25f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui 26f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui#include <android-base/file.h> 27f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui 2833697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes#include "utils.h" 2933697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes 3065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott HughesTEST(pty, openpty) { 3165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes int master, slave; 3265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes char name[32]; 3365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes struct winsize w = { 123, 456, 9999, 999 }; 3465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_EQ(0, openpty(&master, &slave, name, NULL, &w)); 3565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_NE(-1, master); 3665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_NE(-1, slave); 3765f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_NE(master, slave); 3865f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 3965f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes char tty_name[32]; 4065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_EQ(0, ttyname_r(slave, tty_name, sizeof(tty_name))); 4165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_STREQ(tty_name, name); 4265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 4365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes struct winsize w_actual; 4465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_EQ(0, ioctl(slave, TIOCGWINSZ, &w_actual)); 4565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_EQ(w_actual.ws_row, w.ws_row); 4665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_EQ(w_actual.ws_col, w.ws_col); 4765f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_EQ(w_actual.ws_xpixel, w.ws_xpixel); 4865f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_EQ(w_actual.ws_ypixel, w.ws_ypixel); 4965f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 5065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes close(master); 5165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes close(slave); 5265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes} 5365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 5465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott HughesTEST(pty, forkpty) { 5565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes pid_t sid = getsid(0); 5665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 5765f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes int master; 5865f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes pid_t pid = forkpty(&master, NULL, NULL, NULL); 5965f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_NE(-1, pid); 6065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 6165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes if (pid == 0) { 6265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes // We're the child. 6365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_NE(sid, getsid(0)); 6465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes _exit(0); 6565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes } 6665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 6765f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes ASSERT_EQ(sid, getsid(0)); 6865f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 6933697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes AssertChildExited(pid, 0); 7065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes 7165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes close(master); 7265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes} 73f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui 74f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cuistruct PtyReader_28979140_Arg { 75c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko int main_cpu_id; 76c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko int slave_fd; 77c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko uint32_t data_count; 78c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko bool finished; 79c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko std::atomic<bool> matched; 80f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui}; 81f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui 82f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cuistatic void PtyReader_28979140(PtyReader_28979140_Arg* arg) { 83f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui arg->finished = false; 84f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui cpu_set_t cpus; 85f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_EQ(0, sched_getaffinity(0, sizeof(cpu_set_t), &cpus)); 86c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko CPU_CLR(arg->main_cpu_id, &cpus); 87f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_EQ(0, sched_setaffinity(0, sizeof(cpu_set_t), &cpus)); 88f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui 89f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui uint32_t counter = 0; 90f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui while (counter <= arg->data_count) { 91f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui char buf[4096]; // Use big buffer to read to hit the bug more easily. 92f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui size_t to_read = std::min(sizeof(buf), (arg->data_count + 1 - counter) * sizeof(uint32_t)); 93f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_TRUE(android::base::ReadFully(arg->slave_fd, buf, to_read)); 94f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui size_t num_of_value = to_read / sizeof(uint32_t); 95f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui uint32_t* p = reinterpret_cast<uint32_t*>(buf); 96f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui while (num_of_value-- > 0) { 97f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui if (*p++ != counter++) { 98f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui arg->matched = false; 99f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui } 100f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui } 101f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui } 102f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui close(arg->slave_fd); 103f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui arg->finished = true; 104f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui} 105f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui 106f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin CuiTEST(pty, bug_28979140) { 107f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui // This test is to test a kernel bug, which uses a lock free ring-buffer to 108f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui // pass data through a raw pty, but missing necessary memory barriers. 109c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko cpu_set_t cpus; 110c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko ASSERT_EQ(0, sched_getaffinity(0, sizeof(cpu_set_t), &cpus)); 111c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko if (CPU_COUNT(&cpus) < 2) { 112f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui GTEST_LOG_(INFO) << "This test tests bug happens only on multiprocessors."; 113f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui return; 114f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui } 115f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui constexpr uint32_t TEST_DATA_COUNT = 200000; 116f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui 117f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui // 1. Open raw pty. 118f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui int master; 119f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui int slave; 120f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_EQ(0, openpty(&master, &slave, nullptr, nullptr, nullptr)); 121f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui termios tattr; 122f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_EQ(0, tcgetattr(slave, &tattr)); 123f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui cfmakeraw(&tattr); 124f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_EQ(0, tcsetattr(slave, TCSADRAIN, &tattr)); 125f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui 126c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko // 2. Make master thread and slave thread running on different cpus: 127c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko // master thread uses first available cpu, and slave thread uses other cpus. 128f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui PtyReader_28979140_Arg arg; 129c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko arg.main_cpu_id = -1; 130c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko for (int i = 0; i < CPU_SETSIZE; i++) { 131c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko if (CPU_ISSET(i, &cpus)) { 132c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko arg.main_cpu_id = i; 133c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko break; 134c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko } 135c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko } 136c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko ASSERT_GE(arg.main_cpu_id, 0); 137c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko 138c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko // 3. Create thread for slave reader. 139c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko pthread_t thread; 140f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui arg.slave_fd = slave; 141f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui arg.data_count = TEST_DATA_COUNT; 142f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui arg.matched = true; 143f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_EQ(0, pthread_create(&thread, nullptr, 144f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui reinterpret_cast<void*(*)(void*)>(PtyReader_28979140), 145f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui &arg)); 146f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui 147f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui CPU_ZERO(&cpus); 148c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko CPU_SET(arg.main_cpu_id, &cpus); 149f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_EQ(0, sched_setaffinity(0, sizeof(cpu_set_t), &cpus)); 150f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui 151f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui // 4. Send data to slave. 152f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui uint32_t counter = 0; 153f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui while (counter <= TEST_DATA_COUNT) { 154f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_TRUE(android::base::WriteFully(master, &counter, sizeof(counter))); 155f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_TRUE(arg.matched) << "failed at count = " << counter; 156f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui counter++; 157f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui } 158f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_EQ(0, pthread_join(thread, nullptr)); 159f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_TRUE(arg.finished); 160f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui ASSERT_TRUE(arg.matched); 161f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui close(master); 162f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui} 163