1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <pty.h> 18 19 #include <gtest/gtest.h> 20 21 #include <pthread.h> 22 #include <sys/ioctl.h> 23 24 #include <atomic> 25 26 #include <android-base/file.h> 27 28 #include "utils.h" 29 30 TEST(pty, openpty) { 31 int master, slave; 32 char name[32]; 33 struct winsize w = { 123, 456, 9999, 999 }; 34 ASSERT_EQ(0, openpty(&master, &slave, name, NULL, &w)); 35 ASSERT_NE(-1, master); 36 ASSERT_NE(-1, slave); 37 ASSERT_NE(master, slave); 38 39 char tty_name[32]; 40 ASSERT_EQ(0, ttyname_r(slave, tty_name, sizeof(tty_name))); 41 ASSERT_STREQ(tty_name, name); 42 43 struct winsize w_actual; 44 ASSERT_EQ(0, ioctl(slave, TIOCGWINSZ, &w_actual)); 45 ASSERT_EQ(w_actual.ws_row, w.ws_row); 46 ASSERT_EQ(w_actual.ws_col, w.ws_col); 47 ASSERT_EQ(w_actual.ws_xpixel, w.ws_xpixel); 48 ASSERT_EQ(w_actual.ws_ypixel, w.ws_ypixel); 49 50 close(master); 51 close(slave); 52 } 53 54 TEST(pty, forkpty) { 55 pid_t sid = getsid(0); 56 57 int master; 58 pid_t pid = forkpty(&master, NULL, NULL, NULL); 59 ASSERT_NE(-1, pid); 60 61 if (pid == 0) { 62 // We're the child. 63 ASSERT_NE(sid, getsid(0)); 64 _exit(0); 65 } 66 67 ASSERT_EQ(sid, getsid(0)); 68 69 AssertChildExited(pid, 0); 70 71 close(master); 72 } 73 74 struct PtyReader_28979140_Arg { 75 int main_cpu_id; 76 int slave_fd; 77 uint32_t data_count; 78 bool finished; 79 std::atomic<bool> matched; 80 }; 81 82 static void PtyReader_28979140(PtyReader_28979140_Arg* arg) { 83 arg->finished = false; 84 cpu_set_t cpus; 85 ASSERT_EQ(0, sched_getaffinity(0, sizeof(cpu_set_t), &cpus)); 86 CPU_CLR(arg->main_cpu_id, &cpus); 87 ASSERT_EQ(0, sched_setaffinity(0, sizeof(cpu_set_t), &cpus)); 88 89 uint32_t counter = 0; 90 while (counter <= arg->data_count) { 91 char buf[4096]; // Use big buffer to read to hit the bug more easily. 92 size_t to_read = std::min(sizeof(buf), (arg->data_count + 1 - counter) * sizeof(uint32_t)); 93 ASSERT_TRUE(android::base::ReadFully(arg->slave_fd, buf, to_read)); 94 size_t num_of_value = to_read / sizeof(uint32_t); 95 uint32_t* p = reinterpret_cast<uint32_t*>(buf); 96 while (num_of_value-- > 0) { 97 if (*p++ != counter++) { 98 arg->matched = false; 99 } 100 } 101 } 102 close(arg->slave_fd); 103 arg->finished = true; 104 } 105 106 TEST(pty, bug_28979140) { 107 // This test is to test a kernel bug, which uses a lock free ring-buffer to 108 // pass data through a raw pty, but missing necessary memory barriers. 109 cpu_set_t cpus; 110 ASSERT_EQ(0, sched_getaffinity(0, sizeof(cpu_set_t), &cpus)); 111 if (CPU_COUNT(&cpus) < 2) { 112 GTEST_LOG_(INFO) << "This test tests bug happens only on multiprocessors."; 113 return; 114 } 115 constexpr uint32_t TEST_DATA_COUNT = 200000; 116 117 // 1. Open raw pty. 118 int master; 119 int slave; 120 ASSERT_EQ(0, openpty(&master, &slave, nullptr, nullptr, nullptr)); 121 termios tattr; 122 ASSERT_EQ(0, tcgetattr(slave, &tattr)); 123 cfmakeraw(&tattr); 124 ASSERT_EQ(0, tcsetattr(slave, TCSADRAIN, &tattr)); 125 126 // 2. Make master thread and slave thread running on different cpus: 127 // master thread uses first available cpu, and slave thread uses other cpus. 128 PtyReader_28979140_Arg arg; 129 arg.main_cpu_id = -1; 130 for (int i = 0; i < CPU_SETSIZE; i++) { 131 if (CPU_ISSET(i, &cpus)) { 132 arg.main_cpu_id = i; 133 break; 134 } 135 } 136 ASSERT_GE(arg.main_cpu_id, 0); 137 138 // 3. Create thread for slave reader. 139 pthread_t thread; 140 arg.slave_fd = slave; 141 arg.data_count = TEST_DATA_COUNT; 142 arg.matched = true; 143 ASSERT_EQ(0, pthread_create(&thread, nullptr, 144 reinterpret_cast<void*(*)(void*)>(PtyReader_28979140), 145 &arg)); 146 147 CPU_ZERO(&cpus); 148 CPU_SET(arg.main_cpu_id, &cpus); 149 ASSERT_EQ(0, sched_setaffinity(0, sizeof(cpu_set_t), &cpus)); 150 151 // 4. Send data to slave. 152 uint32_t counter = 0; 153 while (counter <= TEST_DATA_COUNT) { 154 ASSERT_TRUE(android::base::WriteFully(master, &counter, sizeof(counter))); 155 ASSERT_TRUE(arg.matched) << "failed at count = " << counter; 156 counter++; 157 } 158 ASSERT_EQ(0, pthread_join(thread, nullptr)); 159 ASSERT_TRUE(arg.finished); 160 ASSERT_TRUE(arg.matched); 161 close(master); 162 } 163