Line data Source code
1 : /*
2 : * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
12 :
13 : #include <assert.h>
14 : #include <limits>
15 :
16 : namespace webrtc {
17 :
18 : // static
19 0 : Bool XErrorTrap::XServerErrorHandler(Display* display, xReply* rep,
20 : char* /* buf */, int /* len */,
21 : XPointer data) {
22 0 : XErrorTrap* self = reinterpret_cast<XErrorTrap*>(data);
23 :
24 0 : if (rep->generic.type != X_Error ||
25 : // Overflow-safe last_request_read <= last_ignored_request_ for skipping
26 : // async replies from requests before XErrorTrap was created.
27 0 : self->last_ignored_request_ - display->last_request_read <
28 0 : std::numeric_limits<unsigned long>::max() >> 1)
29 0 : return False;
30 :
31 0 : self->last_xserver_error_code_ = rep->error.errorCode;
32 0 : return True;
33 : }
34 :
35 0 : XErrorTrap::XErrorTrap(Display* display)
36 : : display_(display),
37 : last_xserver_error_code_(0),
38 0 : enabled_(true) {
39 : // Use async_handlers instead of XSetErrorHandler(). async_handlers can
40 : // remain in place and then be safely removed at the right time even if a
41 : // handler change happens concurrently on another thread. async_handlers
42 : // are processed first and so can prevent errors reaching the global
43 : // XSetErrorHandler handler. They also will not see errors from or affect
44 : // handling of errors on other Displays, which may be processed on other
45 : // threads.
46 0 : LockDisplay(display);
47 0 : async_handler_.next = display->async_handlers;
48 0 : async_handler_.handler = XServerErrorHandler;
49 0 : async_handler_.data = reinterpret_cast<XPointer>(this);
50 0 : display->async_handlers = &async_handler_;
51 0 : last_ignored_request_ = display->request;
52 0 : UnlockDisplay(display);
53 0 : }
54 :
55 0 : int XErrorTrap::GetLastErrorAndDisable() {
56 0 : assert(enabled_);
57 0 : enabled_ = false;
58 0 : LockDisplay(display_);
59 0 : DeqAsyncHandler(display_, &async_handler_);
60 0 : UnlockDisplay(display_);
61 0 : return last_xserver_error_code_;
62 : }
63 :
64 0 : XErrorTrap::~XErrorTrap() {
65 0 : if (enabled_)
66 0 : GetLastErrorAndDisable();
67 0 : }
68 :
69 : } // namespace webrtc
|