aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-07-02 21:55:22 +0800
committerPo Lu2022-07-02 21:56:59 +0800
commitb25ca542983dc885d69d263cb9719f7f3db416fa (patch)
treef96df4aecc6e9adf2df0f17d5262c121cffce4b6 /src
parent59d109b73c48ca41d240f1fbe10f7349e9df4e31 (diff)
downloademacs-b25ca542983dc885d69d263cb9719f7f3db416fa.tar.gz
emacs-b25ca542983dc885d69d263cb9719f7f3db416fa.zip
Fix error handling for XCB Xlib
* src/xterm.c (xm_send_drop_message) (xm_send_top_level_enter_message, xm_send_drag_motion_message) (xm_send_top_level_leave_message, x_dnd_compute_toplevels) (x_dnd_send_enter, x_dnd_send_position, x_dnd_send_leave) (x_dnd_send_drop, handle_one_xevent, x_catch_errors_with_handler) (x_request_can_fail, x_clean_failable_requests) (x_ignore_errors_for_next_request, x_stop_ignoring_errors) (x_uncatch_errors, x_check_errors, x_had_errors_p, x_error_handler) (frame_set_mouse_pixel_position, x_focus_frame): Record serial sequences instead of simply the next request when ignoring a single request. Use XNextRequest instead of NextRequest, since the latter is unreliable when using Xlib built with XCB. * src/xterm.h (struct x_failable_request): New struct.. (struct x_display_info): Make failable request variables the right type.
Diffstat (limited to 'src')
-rw-r--r--src/xterm.c99
-rw-r--r--src/xterm.h18
2 files changed, 84 insertions, 33 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 0c695324f3b..7ab22f256f6 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1117,6 +1117,7 @@ static void x_scroll_bar_end_update (struct x_display_info *, struct scroll_bar
1117static int x_filter_event (struct x_display_info *, XEvent *); 1117static int x_filter_event (struct x_display_info *, XEvent *);
1118#endif 1118#endif
1119static void x_ignore_errors_for_next_request (struct x_display_info *); 1119static void x_ignore_errors_for_next_request (struct x_display_info *);
1120static void x_stop_ignoring_errors (struct x_display_info *);
1120static void x_clean_failable_requests (struct x_display_info *); 1121static void x_clean_failable_requests (struct x_display_info *);
1121 1122
1122static struct frame *x_tooltip_window_to_frame (struct x_display_info *, 1123static struct frame *x_tooltip_window_to_frame (struct x_display_info *,
@@ -2444,6 +2445,7 @@ xm_send_drop_message (struct x_display_info *dpyinfo, Window source,
2444 2445
2445 x_ignore_errors_for_next_request (dpyinfo); 2446 x_ignore_errors_for_next_request (dpyinfo);
2446 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); 2447 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2448 x_stop_ignoring_errors (dpyinfo);
2447} 2449}
2448 2450
2449static void 2451static void
@@ -2470,6 +2472,7 @@ xm_send_top_level_enter_message (struct x_display_info *dpyinfo, Window source,
2470 2472
2471 x_ignore_errors_for_next_request (dpyinfo); 2473 x_ignore_errors_for_next_request (dpyinfo);
2472 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); 2474 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2475 x_stop_ignoring_errors (dpyinfo);
2473} 2476}
2474 2477
2475static void 2478static void
@@ -2500,6 +2503,7 @@ xm_send_drag_motion_message (struct x_display_info *dpyinfo, Window source,
2500 2503
2501 x_ignore_errors_for_next_request (dpyinfo); 2504 x_ignore_errors_for_next_request (dpyinfo);
2502 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); 2505 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2506 x_stop_ignoring_errors (dpyinfo);
2503} 2507}
2504 2508
2505static void 2509static void
@@ -2558,6 +2562,7 @@ xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source,
2558 2562
2559 x_ignore_errors_for_next_request (dpyinfo); 2563 x_ignore_errors_for_next_request (dpyinfo);
2560 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); 2564 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2565 x_stop_ignoring_errors (dpyinfo);
2561} 2566}
2562 2567
2563static int 2568static int
@@ -3211,6 +3216,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
3211 XShapeSelectInput (dpyinfo->display, 3216 XShapeSelectInput (dpyinfo->display,
3212 toplevels[i], 3217 toplevels[i],
3213 ShapeNotifyMask); 3218 ShapeNotifyMask);
3219 x_stop_ignoring_errors (dpyinfo);
3214 3220
3215#ifndef HAVE_XCB_SHAPE 3221#ifndef HAVE_XCB_SHAPE
3216 x_catch_errors (dpyinfo->display); 3222 x_catch_errors (dpyinfo->display);
@@ -4397,6 +4403,7 @@ x_dnd_send_enter (struct frame *f, Window target, int supported)
4397 4403
4398 x_ignore_errors_for_next_request (dpyinfo); 4404 x_ignore_errors_for_next_request (dpyinfo);
4399 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); 4405 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4406 x_stop_ignoring_errors (dpyinfo);
4400} 4407}
4401 4408
4402static void 4409static void
@@ -4459,6 +4466,7 @@ x_dnd_send_position (struct frame *f, Window target, int supported,
4459 { 4466 {
4460 x_ignore_errors_for_next_request (dpyinfo); 4467 x_ignore_errors_for_next_request (dpyinfo);
4461 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); 4468 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4469 x_stop_ignoring_errors (dpyinfo);
4462 4470
4463 x_dnd_waiting_for_status_window = target; 4471 x_dnd_waiting_for_status_window = target;
4464 } 4472 }
@@ -4484,6 +4492,7 @@ x_dnd_send_leave (struct frame *f, Window target)
4484 4492
4485 x_ignore_errors_for_next_request (dpyinfo); 4493 x_ignore_errors_for_next_request (dpyinfo);
4486 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); 4494 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4495 x_stop_ignoring_errors (dpyinfo);
4487} 4496}
4488 4497
4489static bool 4498static bool
@@ -4516,6 +4525,7 @@ x_dnd_send_drop (struct frame *f, Window target, Time timestamp,
4516 4525
4517 x_ignore_errors_for_next_request (dpyinfo); 4526 x_ignore_errors_for_next_request (dpyinfo);
4518 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); 4527 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4528 x_stop_ignoring_errors (dpyinfo);
4519 return true; 4529 return true;
4520} 4530}
4521 4531
@@ -16454,6 +16464,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
16454 XSendEvent (dpyinfo->display, target, 16464 XSendEvent (dpyinfo->display, target,
16455 False, NoEventMask, 16465 False, NoEventMask,
16456 &x_dnd_pending_send_position); 16466 &x_dnd_pending_send_position);
16467 x_stop_ignoring_errors (dpyinfo);
16457 x_dnd_pending_send_position.type = 0; 16468 x_dnd_pending_send_position.type = 0;
16458 16469
16459 /* Since we sent another XdndPosition message, we 16470 /* Since we sent another XdndPosition message, we
@@ -22991,7 +23002,8 @@ x_error_catcher (Display *display, XErrorEvent *event,
22991 There is no need to use this mechanism for ignoring errors from 23002 There is no need to use this mechanism for ignoring errors from
22992 single asynchronous requests, such as sending a ClientMessage to a 23003 single asynchronous requests, such as sending a ClientMessage to a
22993 window that might no longer exist. Use 23004 window that might no longer exist. Use
22994 x_ignore_errors_for_next_request instead. */ 23005 x_ignore_errors_for_next_request (paired with
23006 x_stop_ignoring_errors) instead. */
22995 23007
22996void 23008void
22997x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler, 23009x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler,
@@ -23004,7 +23016,7 @@ x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler,
23004 data->handler = handler; 23016 data->handler = handler;
23005 data->handler_data = handler_data; 23017 data->handler_data = handler_data;
23006 data->prev = x_error_message; 23018 data->prev = x_error_message;
23007 data->first_request = NextRequest (dpy); 23019 data->first_request = XNextRequest (dpy);
23008 x_error_message = data; 23020 x_error_message = data;
23009 23021
23010 ++x_error_message_count; 23022 ++x_error_message_count;
@@ -23018,17 +23030,21 @@ x_catch_errors (Display *dpy)
23018 23030
23019/* Return if errors for REQUEST should be ignored even if there is no 23031/* Return if errors for REQUEST should be ignored even if there is no
23020 error handler applied. */ 23032 error handler applied. */
23021static unsigned long * 23033static struct x_failable_request *
23022x_request_can_fail (struct x_display_info *dpyinfo, 23034x_request_can_fail (struct x_display_info *dpyinfo,
23023 unsigned long request) 23035 unsigned long request)
23024{ 23036{
23025 unsigned long *failable_requests; 23037 struct x_failable_request *failable_requests;
23026 23038
23027 for (failable_requests = dpyinfo->failable_requests; 23039 for (failable_requests = dpyinfo->failable_requests;
23028 failable_requests < dpyinfo->next_failable_request; 23040 failable_requests < dpyinfo->next_failable_request;
23029 failable_requests++) 23041 failable_requests++)
23030 { 23042 {
23031 if (*failable_requests == request) 23043 if (X_COMPARE_SERIALS (request, >=,
23044 failable_requests->start)
23045 && (!failable_requests->end
23046 || X_COMPARE_SERIALS (request, <=,
23047 failable_requests->end)))
23032 return failable_requests; 23048 return failable_requests;
23033 } 23049 }
23034 23050
@@ -23040,13 +23056,17 @@ x_request_can_fail (struct x_display_info *dpyinfo,
23040static void 23056static void
23041x_clean_failable_requests (struct x_display_info *dpyinfo) 23057x_clean_failable_requests (struct x_display_info *dpyinfo)
23042{ 23058{
23043 unsigned long *first, *last; 23059 struct x_failable_request *first, *last;
23044 23060
23045 last = dpyinfo->next_failable_request; 23061 last = dpyinfo->next_failable_request;
23046 23062
23047 for (first = dpyinfo->failable_requests; first < last; first++) 23063 for (first = dpyinfo->failable_requests; first < last; first++)
23048 { 23064 {
23049 if (*first > LastKnownRequestProcessed (dpyinfo->display)) 23065 if (X_COMPARE_SERIALS (first->start, >,
23066 LastKnownRequestProcessed (dpyinfo->display))
23067 || !first->end
23068 || X_COMPARE_SERIALS (first->end, >,
23069 LastKnownRequestProcessed (dpyinfo->display)))
23050 break; 23070 break;
23051 } 23071 }
23052 23072
@@ -23061,7 +23081,14 @@ x_clean_failable_requests (struct x_display_info *dpyinfo)
23061static void 23081static void
23062x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) 23082x_ignore_errors_for_next_request (struct x_display_info *dpyinfo)
23063{ 23083{
23064 unsigned long *request, *max; 23084 struct x_failable_request *request, *max;
23085
23086 if ((dpyinfo->next_failable_request
23087 != dpyinfo->failable_requests)
23088 && (dpyinfo->next_failable_request - 1)->end == 0)
23089 /* A new sequence should never be started before an old one
23090 finishes. Use `x_catch_errors' to nest error handlers. */
23091 emacs_abort ();
23065 23092
23066 request = dpyinfo->next_failable_request; 23093 request = dpyinfo->next_failable_request;
23067 max = dpyinfo->failable_requests + N_FAILABLE_REQUESTS; 23094 max = dpyinfo->failable_requests + N_FAILABLE_REQUESTS;
@@ -23071,7 +23098,7 @@ x_ignore_errors_for_next_request (struct x_display_info *dpyinfo)
23071 /* There is no point in making this extra sync if all requests 23098 /* There is no point in making this extra sync if all requests
23072 are known to have been fully processed. */ 23099 are known to have been fully processed. */
23073 if ((LastKnownRequestProcessed (dpyinfo->display) 23100 if ((LastKnownRequestProcessed (dpyinfo->display)
23074 != NextRequest (dpyinfo->display) - 1)) 23101 != XNextRequest (dpyinfo->display) - 1))
23075 XSync (dpyinfo->display, False); 23102 XSync (dpyinfo->display, False);
23076 23103
23077 x_clean_failable_requests (dpyinfo); 23104 x_clean_failable_requests (dpyinfo);
@@ -23083,10 +23110,21 @@ x_ignore_errors_for_next_request (struct x_display_info *dpyinfo)
23083 function. */ 23110 function. */
23084 emacs_abort (); 23111 emacs_abort ();
23085 23112
23086 *request = NextRequest (dpyinfo->display); 23113 request->start = XNextRequest (dpyinfo->display);
23114 request->end = 0;
23115
23087 dpyinfo->next_failable_request++; 23116 dpyinfo->next_failable_request++;
23088} 23117}
23089 23118
23119static void
23120x_stop_ignoring_errors (struct x_display_info *dpyinfo)
23121{
23122 struct x_failable_request *range;
23123
23124 range = dpyinfo->next_failable_request - 1;
23125 range->end = XNextRequest (dpyinfo->display) - 1;
23126}
23127
23090/* Undo the last x_catch_errors call. 23128/* Undo the last x_catch_errors call.
23091 DPY should be the display that was passed to x_catch_errors. 23129 DPY should be the display that was passed to x_catch_errors.
23092 23130
@@ -23134,10 +23172,10 @@ x_uncatch_errors (void)
23134 /* There is no point in making this extra sync if all requests 23172 /* There is no point in making this extra sync if all requests
23135 are known to have been fully processed. */ 23173 are known to have been fully processed. */
23136 && (LastKnownRequestProcessed (x_error_message->dpy) 23174 && (LastKnownRequestProcessed (x_error_message->dpy)
23137 != NextRequest (x_error_message->dpy) - 1) 23175 != XNextRequest (x_error_message->dpy) - 1)
23138 /* Likewise if no request was made since the trap was 23176 /* Likewise if no request was made since the trap was
23139 installed. */ 23177 installed. */
23140 && (NextRequest (x_error_message->dpy) 23178 && (XNextRequest (x_error_message->dpy)
23141 > x_error_message->first_request)) 23179 > x_error_message->first_request))
23142 { 23180 {
23143 XSync (x_error_message->dpy, False); 23181 XSync (x_error_message->dpy, False);
@@ -23171,8 +23209,8 @@ x_check_errors (Display *dpy, const char *format)
23171 /* There is no point in making this extra sync if all requests 23209 /* There is no point in making this extra sync if all requests
23172 are known to have been fully processed. */ 23210 are known to have been fully processed. */
23173 if ((LastKnownRequestProcessed (dpy) 23211 if ((LastKnownRequestProcessed (dpy)
23174 != NextRequest (dpy) - 1) 23212 != XNextRequest (dpy) - 1)
23175 && (NextRequest (dpy) 23213 && (XNextRequest (dpy)
23176 > x_error_message->first_request)) 23214 > x_error_message->first_request))
23177 XSync (dpy, False); 23215 XSync (dpy, False);
23178 23216
@@ -23206,8 +23244,8 @@ x_had_errors_p (Display *dpy)
23206 23244
23207 /* Make sure to catch any errors incurred so far. */ 23245 /* Make sure to catch any errors incurred so far. */
23208 if ((LastKnownRequestProcessed (dpy) 23246 if ((LastKnownRequestProcessed (dpy)
23209 != NextRequest (dpy) - 1) 23247 != XNextRequest (dpy) - 1)
23210 && (NextRequest (dpy) 23248 && (XNextRequest (dpy)
23211 > x_error_message->first_request)) 23249 > x_error_message->first_request))
23212 XSync (dpy, False); 23250 XSync (dpy, False);
23213 23251
@@ -23471,7 +23509,7 @@ x_error_handler (Display *display, XErrorEvent *event)
23471{ 23509{
23472 struct x_error_message_stack *stack; 23510 struct x_error_message_stack *stack;
23473 struct x_display_info *dpyinfo; 23511 struct x_display_info *dpyinfo;
23474 unsigned long *fail, *last; 23512 struct x_failable_request *fail, *last;
23475 23513
23476#if defined USE_GTK && defined HAVE_GTK3 23514#if defined USE_GTK && defined HAVE_GTK3
23477 if ((event->error_code == BadMatch 23515 if ((event->error_code == BadMatch
@@ -23488,13 +23526,17 @@ x_error_handler (Display *display, XErrorEvent *event)
23488 23526
23489 if (fail) 23527 if (fail)
23490 { 23528 {
23491 /* Now that this request has been handled, remove it from 23529 /* Now that this request sequence has been fully handled,
23492 the list of requests that can fail. */ 23530 remove it from the list of requests that can fail. */
23493 last = dpyinfo->next_failable_request; 23531
23494 memmove (&dpyinfo->failable_requests, fail, 23532 if (event->serial == fail->end)
23495 sizeof *fail * (last - fail)); 23533 {
23496 dpyinfo->next_failable_request = (dpyinfo->failable_requests 23534 last = dpyinfo->next_failable_request;
23497 + (last - fail)); 23535 memmove (&dpyinfo->failable_requests, fail,
23536 sizeof *fail * (last - fail));
23537 dpyinfo->next_failable_request = (dpyinfo->failable_requests
23538 + (last - fail));
23539 }
23498 23540
23499 return 0; 23541 return 0;
23500 } 23542 }
@@ -24882,11 +24924,9 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
24882 &deviceid)) 24924 &deviceid))
24883 { 24925 {
24884 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f)); 24926 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f));
24885 24927 XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
24886 XIWarpPointer (FRAME_X_DISPLAY (f), 24928 FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y);
24887 deviceid, None, 24929 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
24888 FRAME_X_WINDOW (f),
24889 0, 0, 0, 0, pix_x, pix_y);
24890 } 24930 }
24891 } 24931 }
24892 else 24932 else
@@ -25025,6 +25065,7 @@ x_focus_frame (struct frame *f, bool noactivate)
25025 x_ignore_errors_for_next_request (dpyinfo); 25065 x_ignore_errors_for_next_request (dpyinfo);
25026 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 25066 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
25027 RevertToParent, CurrentTime); 25067 RevertToParent, CurrentTime);
25068 x_stop_ignoring_errors (dpyinfo);
25028 25069
25029 if (!noactivate) 25070 if (!noactivate)
25030 x_ewmh_activate_frame (f); 25071 x_ewmh_activate_frame (f);
diff --git a/src/xterm.h b/src/xterm.h
index eee76724268..7c09073d765 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -261,6 +261,16 @@ struct xi_device_t
261Status x_parse_color (struct frame *f, const char *color_name, 261Status x_parse_color (struct frame *f, const char *color_name,
262 XColor *color); 262 XColor *color);
263 263
264struct x_failable_request
265{
266 /* The first request making up this sequence. */
267 unsigned long start;
268
269 /* If this is zero, then the request has not yet been made.
270 Otherwise, this is the request that ends this sequence. */
271 unsigned long end;
272};
273
264 274
265/* For each X display, we have a structure that records 275/* For each X display, we have a structure that records
266 information about it. */ 276 information about it. */
@@ -746,12 +756,12 @@ struct x_display_info
746 int screen_mm_width; 756 int screen_mm_width;
747 int screen_mm_height; 757 int screen_mm_height;
748 758
749 /* Circular buffer of request serials to ignore inside an error 759 /* Circular buffer of request serial ranges to ignore inside an
750 handler in increasing order. */ 760 error handler in increasing order. */
751 unsigned long failable_requests[N_FAILABLE_REQUESTS]; 761 struct x_failable_request failable_requests[N_FAILABLE_REQUESTS];
752 762
753 /* Pointer to the next request in `failable_requests'. */ 763 /* Pointer to the next request in `failable_requests'. */
754 unsigned long *next_failable_request; 764 struct x_failable_request *next_failable_request;
755}; 765};
756 766
757#ifdef HAVE_X_I18N 767#ifdef HAVE_X_I18N