Mir

Merge lp:~vanvugt/mir/fix-1169020 into lp:mir

Proposed by Daniel van Vugt on 2016-08-03
Status: Work in progress
Proposed branch: lp:~vanvugt/mir/fix-1169020
Merge into: lp:mir
Diff against target: 327 lines (+67/-110)
2 files modified
src/platforms/mesa/server/kms/linux_virtual_terminal.cpp (+54/-96)
tests/unit-tests/graphics/mesa/kms/test_linux_virtual_terminal.cpp (+13/-14)
To merge this branch: bzr merge lp:~vanvugt/mir/fix-1169020
Reviewer Review Type Date Requested Status
Mir development team 2016-08-03 Pending
Review via email: mp+301892@code.launchpad.net

Commit message

Add (restore) support for starting Mir without VTs, or without
permission to manipulate VTs (LP: #1169020)

All you need is appropriate permission to /dev/dri/*

If VTs are available and we have permission to manipulate them, then
the old existing logic remains the same as ever. If VTs are not
available or we don't have permission to modify them, don't crash, just
start rendering anyway. It will often work providing you have sufficient
access to the graphics device.

Description of the change

Work in progress...

This is no longer a priority for the device device bring-up. I might get back to it at a later date when I revive and need it for Chromebook support again.

To post a comment you must log in.

Unmerged revisions

3624. By Daniel van Vugt on 2016-08-03

Fix test failures

TODO: Fix 'Uninteresting mock function call' messages

3623. By Daniel van Vugt on 2016-08-03

First working prototype

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/platforms/mesa/server/kms/linux_virtual_terminal.cpp'
2--- src/platforms/mesa/server/kms/linux_virtual_terminal.cpp 2016-01-29 08:18:22 +0000
3+++ src/platforms/mesa/server/kms/linux_virtual_terminal.cpp 2016-08-03 10:00:58 +0000
4@@ -19,16 +19,14 @@
5 #include "linux_virtual_terminal.h"
6 #include "mir/graphics/display_report.h"
7 #include "mir/graphics/event_handler_register.h"
8-
9-#include <boost/throw_exception.hpp>
10-#include <boost/exception/errinfo_errno.hpp>
11-#include <boost/exception/errinfo_file_name.hpp>
12+#include "mir/log.h"
13
14 #include <vector>
15 #include <string>
16 #include <sstream>
17 #include <stdexcept>
18 #include <csignal>
19+#include <cstring>
20
21 #include <linux/vt.h>
22 #include <linux/kd.h>
23@@ -36,6 +34,14 @@
24
25 namespace mgm = mir::graphics::mesa;
26
27+namespace mir
28+{
29+ void perror(char const* message)
30+ {
31+ mir::log_warning("%s (%s)", message, strerror(errno));
32+ }
33+}
34+
35 mgm::LinuxVirtualTerminal::LinuxVirtualTerminal(std::shared_ptr<VTFileOperations> const& fops,
36 std::unique_ptr<PosixProcessOperations> pops,
37 int vt_number,
38@@ -51,48 +57,32 @@
39 active{true}
40 {
41 struct termios tcattr;
42- if (fops->ioctl(vt_fd.fd(), KDGETMODE, &prev_kd_mode) < 0)
43- {
44- BOOST_THROW_EXCEPTION(
45- boost::enable_error_info(
46- std::runtime_error("Failed to get current VT mode"))
47- << boost::errinfo_errno(errno));
48- }
49-
50- if (fops->ioctl(vt_fd.fd(), VT_GETMODE, &prev_vt_mode) < 0)
51- {
52- BOOST_THROW_EXCEPTION(
53- boost::enable_error_info(
54- std::runtime_error("Failed to get the current VT"))
55- << boost::errinfo_errno(errno));
56- }
57-
58- if (fops->ioctl(vt_fd.fd(), KDGKBMODE, &prev_tty_mode) < 0)
59- {
60- BOOST_THROW_EXCEPTION(
61- boost::enable_error_info(
62- std::runtime_error("Failed to get the current TTY mode"))
63- << boost::errinfo_errno(errno));
64- }
65- if (fops->ioctl(vt_fd.fd(), KDSKBMODE, K_OFF) < 0)
66- {
67- BOOST_THROW_EXCEPTION(
68- boost::enable_error_info(
69- std::runtime_error("Failed to mute keyboard"))
70- << boost::errinfo_errno(errno));
71- }
72-
73- fops->tcgetattr(vt_fd.fd(), &prev_tcattr);
74- tcattr = prev_tcattr;
75- tcattr.c_iflag = IGNPAR | IGNBRK;
76- cfsetispeed(&tcattr, B9600);
77- tcattr.c_oflag = 0;
78- cfsetospeed(&tcattr, B9600);
79- tcattr.c_cflag = CREAD | CS8;
80- tcattr.c_lflag = 0;
81- tcattr.c_cc[VTIME] = 0;
82- tcattr.c_cc[VMIN] = 1;
83- fops->tcsetattr(vt_fd.fd(), TCSANOW, &tcattr);
84+ if (vt_fd.fd() < 0)
85+ {
86+ mir::log_info("Starting without VT support");
87+ }
88+ else if (fops->ioctl(vt_fd.fd(), KDGETMODE, &prev_kd_mode) < 0)
89+ mir::perror("Failed to get current VT mode");
90+ else if (fops->ioctl(vt_fd.fd(), VT_GETMODE, &prev_vt_mode) < 0)
91+ mir::perror("Failed to get the current VT");
92+ else if (fops->ioctl(vt_fd.fd(), KDGKBMODE, &prev_tty_mode) < 0)
93+ mir::perror("Failed to get the current TTY mode");
94+ else if (fops->ioctl(vt_fd.fd(), KDSKBMODE, K_OFF) < 0)
95+ mir::perror("Failed to mute keyboard");
96+ else
97+ {
98+ fops->tcgetattr(vt_fd.fd(), &prev_tcattr);
99+ tcattr = prev_tcattr;
100+ tcattr.c_iflag = IGNPAR | IGNBRK;
101+ cfsetispeed(&tcattr, B9600);
102+ tcattr.c_oflag = 0;
103+ cfsetospeed(&tcattr, B9600);
104+ tcattr.c_cflag = CREAD | CS8;
105+ tcattr.c_lflag = 0;
106+ tcattr.c_cc[VTIME] = 0;
107+ tcattr.c_cc[VMIN] = 1;
108+ fops->tcsetattr(vt_fd.fd(), TCSANOW, &tcattr);
109+ }
110 }
111
112 mgm::LinuxVirtualTerminal::~LinuxVirtualTerminal() noexcept(true)
113@@ -102,12 +92,9 @@
114
115 void mgm::LinuxVirtualTerminal::set_graphics_mode()
116 {
117- if (fops->ioctl(vt_fd.fd(), KDSETMODE, KD_GRAPHICS) < 0)
118+ if (vt_fd.fd() >= 0 && fops->ioctl(vt_fd.fd(), KDSETMODE, KD_GRAPHICS) < 0)
119 {
120- BOOST_THROW_EXCEPTION(
121- boost::enable_error_info(
122- std::runtime_error("Failed to set VT to graphics mode"))
123- << boost::errinfo_errno(errno));
124+ mir::perror("Failed to set VT to graphics mode");
125 }
126 }
127
128@@ -116,6 +103,9 @@
129 std::function<bool()> const& switch_away,
130 std::function<bool()> const& switch_back)
131 {
132+ if (vt_fd.fd() < 0)
133+ return;
134+
135 handlers.register_signal_handler(
136 {SIGUSR1},
137 make_module_ptr<std::function<void(int)>>(
138@@ -160,10 +150,7 @@
139
140 if (fops->ioctl(vt_fd.fd(), VT_SETMODE, &vtm) < 0)
141 {
142- BOOST_THROW_EXCEPTION(
143- boost::enable_error_info(
144- std::runtime_error("Failed to set the current VT mode"))
145- << boost::errinfo_errno(errno));
146+ mir::perror("Failed to set the current VT mode");
147 }
148 }
149
150@@ -215,10 +202,7 @@
151 }
152
153 if (active_vt < 0)
154- {
155- BOOST_THROW_EXCEPTION(
156- std::runtime_error("Failed to find the current VT"));
157- }
158+ mir::perror("Failed to find the current VT");
159
160 return active_vt;
161 }
162@@ -229,6 +213,8 @@
163 if (vt_number <= 0)
164 {
165 vt_number = find_active_vt_number();
166+ if (vt_number < 0)
167+ vt_number = 0; // tty0 means try whichever one is on screen
168 activate = false;
169 }
170
171@@ -243,22 +229,11 @@
172 // and group leader if we are not already the session leader
173 if (pops->getpid() != pops->getsid(0))
174 {
175- if (pops->getpid() == pops->getpgid(0) && pops->setpgid(0, pops->getpgid(pops->getppid())) < 0)
176- {
177- BOOST_THROW_EXCEPTION(
178- boost::enable_error_info(
179- std::runtime_error("Failed to stop being a process group"))
180- << boost::errinfo_errno(errno));
181- }
182-
183- /* become process group leader */
184- if (pops->setsid() < 0)
185- {
186- BOOST_THROW_EXCEPTION(
187- boost::enable_error_info(
188- std::runtime_error("Failed to become session leader"))
189- << boost::errinfo_errno(errno));
190- }
191+ if (pops->getpid() == pops->getpgid(0) &&
192+ pops->setpgid(0, pops->getpgid(pops->getppid())) < 0)
193+ mir::perror("Failed to stop being a process group");
194+ else if (pops->setsid() < 0) // become process group leader
195+ mir::perror("Failed to become session leader");
196 }
197 }
198
199@@ -266,33 +241,16 @@
200
201 if (vt_fd < 0)
202 {
203- BOOST_THROW_EXCEPTION(
204- boost::enable_error_info(
205- std::runtime_error("Failed to open current VT"))
206- << boost::errinfo_file_name(active_vt_path)
207- << boost::errinfo_errno(errno));
208+ mir::perror("Failed to open current VT");
209 }
210-
211- if (activate)
212+ else if (activate)
213 {
214 auto status = fops->ioctl(vt_fd, VT_ACTIVATE, vt_number);
215 if (status < 0)
216- {
217- BOOST_THROW_EXCEPTION(
218- boost::enable_error_info(
219- std::runtime_error("Failed to activate VT"))
220- << boost::errinfo_file_name(active_vt_path)
221- << boost::errinfo_errno(errno));
222- }
223+ mir::perror("Failed to activate VT");
224 status = fops->ioctl(vt_fd, VT_WAITACTIVE, vt_number);
225 if (status < 0)
226- {
227- BOOST_THROW_EXCEPTION(
228- boost::enable_error_info(
229- std::runtime_error("Failed to wait for VT to become active"))
230- << boost::errinfo_file_name(active_vt_path)
231- << boost::errinfo_errno(errno));
232- }
233+ mir::perror("Failed to wait for VT to become active");
234 }
235
236 return vt_fd;
237
238=== modified file 'tests/unit-tests/graphics/mesa/kms/test_linux_virtual_terminal.cpp'
239--- tests/unit-tests/graphics/mesa/kms/test_linux_virtual_terminal.cpp 2016-01-29 08:18:22 +0000
240+++ tests/unit-tests/graphics/mesa/kms/test_linux_virtual_terminal.cpp 2016-08-03 10:00:58 +0000
241@@ -283,7 +283,7 @@
242 mgm::LinuxVirtualTerminal vt{fops, std::move(pops), 0, null_report};
243 }
244
245-TEST_F(LinuxVirtualTerminalTest, failure_to_find_current_vt_throws)
246+TEST_F(LinuxVirtualTerminalTest, failure_to_find_current_vt_never_throws)
247 {
248 using namespace testing;
249
250@@ -299,16 +299,15 @@
251 .WillOnce(Return(0));
252
253 EXPECT_CALL(mock_fops, open(StrEq("/dev/tty0"), _))
254- .WillOnce(Return(-1))
255- .WillOnce(Return(-1));
256+ .WillRepeatedly(Return(-1));
257
258 auto fops = mt::fake_shared<mgm::VTFileOperations>(mock_fops);
259 auto pops = std::unique_ptr<mgm::PosixProcessOperations>(new StubPosixProcessOperations());
260 auto null_report = mr::null_display_report();
261
262- EXPECT_THROW({
263+ EXPECT_NO_THROW({
264 mgm::LinuxVirtualTerminal vt(fops, std::move(pops), 0, null_report);
265- }, std::runtime_error);
266+ });
267 }
268
269 TEST_F(LinuxVirtualTerminalTest, does_not_restore_vt_mode_if_vt_process)
270@@ -354,7 +353,7 @@
271 vt.set_graphics_mode();
272 }
273
274-TEST_F(LinuxVirtualTerminalTest, failure_to_set_graphics_mode_throws)
275+TEST_F(LinuxVirtualTerminalTest, failure_to_set_graphics_mode_never_throws)
276 {
277 using namespace testing;
278
279@@ -375,9 +374,9 @@
280 auto null_report = mr::null_display_report();
281
282 mgm::LinuxVirtualTerminal vt(fops, std::move(pops), 0, null_report);
283- EXPECT_THROW({
284+ EXPECT_NO_THROW({
285 vt.set_graphics_mode();
286- }, std::runtime_error);
287+ });
288 }
289
290 TEST_F(LinuxVirtualTerminalTest, uses_sigusr1_for_switch_handling)
291@@ -577,7 +576,7 @@
292 mgm::LinuxVirtualTerminal vt{fops, std::move(pops), vt_num, null_report};
293 }
294
295-TEST_F(LinuxVirtualTerminalTest, exception_if_setting_process_group_fails)
296+TEST_F(LinuxVirtualTerminalTest, no_exception_if_setting_process_group_fails)
297 {
298 using namespace testing;
299
300@@ -607,12 +606,12 @@
301 .Times(1)
302 .WillOnce(Return(-1));
303
304- EXPECT_THROW({
305+ EXPECT_NO_THROW({
306 mgm::LinuxVirtualTerminal vt(fops, std::move(pops), vt_num, null_report);
307- }, std::runtime_error);
308+ });
309 }
310
311-TEST_F(LinuxVirtualTerminalTest, exception_if_becoming_session_leader_fails)
312+TEST_F(LinuxVirtualTerminalTest, no_exception_if_becoming_session_leader_fails)
313 {
314 using namespace testing;
315
316@@ -645,9 +644,9 @@
317 .Times(1)
318 .WillOnce(Return(-1));
319
320- EXPECT_THROW({
321+ EXPECT_NO_THROW({
322 mgm::LinuxVirtualTerminal vt(fops, std::move(pops), vt_num, null_report);
323- }, std::runtime_error);
324+ });
325 }
326
327 TEST_F(LinuxVirtualTerminalTest, restores_keyboard_and_graphics)

Subscribers

People subscribed via source and target branches