• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(pty,openpty)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 
TEST(pty,forkpty)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 slave_fd;
76  uint32_t data_count;
77  bool finished;
78  std::atomic<bool> matched;
79 };
80 
PtyReader_28979140(PtyReader_28979140_Arg * arg)81 static void PtyReader_28979140(PtyReader_28979140_Arg* arg) {
82   arg->finished = false;
83   cpu_set_t cpus;
84   ASSERT_EQ(0, sched_getaffinity(0, sizeof(cpu_set_t), &cpus));
85   CPU_CLR(0, &cpus);
86   ASSERT_EQ(0, sched_setaffinity(0, sizeof(cpu_set_t), &cpus));
87 
88   uint32_t counter = 0;
89   while (counter <= arg->data_count) {
90     char buf[4096];  // Use big buffer to read to hit the bug more easily.
91     size_t to_read = std::min(sizeof(buf), (arg->data_count + 1 - counter) * sizeof(uint32_t));
92     ASSERT_TRUE(android::base::ReadFully(arg->slave_fd, buf, to_read));
93     size_t num_of_value = to_read / sizeof(uint32_t);
94     uint32_t* p = reinterpret_cast<uint32_t*>(buf);
95     while (num_of_value-- > 0) {
96       if (*p++ != counter++) {
97         arg->matched = false;
98       }
99     }
100   }
101   close(arg->slave_fd);
102   arg->finished = true;
103 }
104 
TEST(pty,bug_28979140)105 TEST(pty, bug_28979140) {
106   // This test is to test a kernel bug, which uses a lock free ring-buffer to
107   // pass data through a raw pty, but missing necessary memory barriers.
108   if (sysconf(_SC_NPROCESSORS_ONLN) == 1) {
109     GTEST_LOG_(INFO) << "This test tests bug happens only on multiprocessors.";
110     return;
111   }
112   constexpr uint32_t TEST_DATA_COUNT = 200000;
113 
114   // 1. Open raw pty.
115   int master;
116   int slave;
117   ASSERT_EQ(0, openpty(&master, &slave, nullptr, nullptr, nullptr));
118   termios tattr;
119   ASSERT_EQ(0, tcgetattr(slave, &tattr));
120   cfmakeraw(&tattr);
121   ASSERT_EQ(0, tcsetattr(slave, TCSADRAIN, &tattr));
122 
123   // 2. Create thread for slave reader.
124   pthread_t thread;
125   PtyReader_28979140_Arg arg;
126   arg.slave_fd = slave;
127   arg.data_count = TEST_DATA_COUNT;
128   arg.matched = true;
129   ASSERT_EQ(0, pthread_create(&thread, nullptr,
130                               reinterpret_cast<void*(*)(void*)>(PtyReader_28979140),
131                               &arg));
132 
133   // 3. Make master thread and slave thread running on different cpus:
134   // master thread uses cpu 0, and slave thread uses other cpus.
135   cpu_set_t cpus;
136   CPU_ZERO(&cpus);
137   CPU_SET(0, &cpus);
138   ASSERT_EQ(0, sched_setaffinity(0, sizeof(cpu_set_t), &cpus));
139 
140   // 4. Send data to slave.
141   uint32_t counter = 0;
142   while (counter <= TEST_DATA_COUNT) {
143     ASSERT_TRUE(android::base::WriteFully(master, &counter, sizeof(counter)));
144     ASSERT_TRUE(arg.matched) << "failed at count = " << counter;
145     counter++;
146   }
147   ASSERT_EQ(0, pthread_join(thread, nullptr));
148   ASSERT_TRUE(arg.finished);
149   ASSERT_TRUE(arg.matched);
150   close(master);
151 }
152