commit 7d978266916fbc463b2bffcefbc6a93cdae3d269
parent 1f4ced49814fdc750b5d7eb7be621d0457ae1098
Author: Kyle Milz <krwmilz@gmail.com>
Date: Sat, 11 Sep 2021 15:41:29 +0000
remove signal handling
The only regressions i have noticed from this are
- the printing dialog output does not update
- drawing a page cannot be interrupted midway through a draw
This greatly simplifies the event loop, and removes one instance of
setjmp() and friends.
Diffstat:
7 files changed, 18 insertions(+), 504 deletions(-)
diff --git a/dvi-draw.c b/dvi-draw.c
@@ -32,7 +32,7 @@ NOTE:
#include "dvi-draw.h" /* drawing_mag */
#include "dvi-init.h" /* check_dvi_file() */
-#include "events.h" /* read_events(), do_color_change(), ... */
+#include "events.h" /* do_color_change(), ... */
#include "font.h" /* load_ft_font() XXX more */
#include "special.h" /* scan_special(), ... */
#include "util.h" /* xfopen(), snum() */
@@ -116,9 +116,6 @@ put_rule(x, y, w, h)
{
if (x < max_x && x + (int) w >= min_x
&& y < max_y && y + (int) h >= min_y) {
- if (--event_counter == 0)
- if (read_events(EV_NOWAIT) & EV_GE_MAG_GONE)
- longjmp(canit_env, 1);
if (fg_active != fg_current) do_color_change();
XFillRectangle(DISP, currwin.win, ruleGC,
x - currwin.base_x, y - currwin.base_y, w ? w : 1, h ? h : 1);
@@ -135,9 +132,6 @@ put_bitmap(bitmap, x, y)
Printf("X(%d,%d)\n", x - currwin.base_x, y - currwin.base_y);
if (x < max_x && x + (int) bitmap->w >= min_x
&& y < max_y && y + (int) bitmap->h >= min_y) {
- if (--event_counter == 0)
- if (read_events(EV_NOWAIT) & EV_GE_MAG_GONE)
- longjmp(canit_env, 1);
if (fg_active != fg_current) do_color_change();
image->width = bitmap->w;
image->height = bitmap->h;
@@ -168,10 +162,6 @@ put_image(g, x, y)
if (x < max_x && x + img->width >= min_x &&
y < max_y && y + img->height >= min_y) {
- if (--event_counter == 0)
- if (read_events(EV_NOWAIT) & EV_GE_MAG_GONE)
- longjmp(canit_env, 1);
-
if (g->fg != fg_current) /* if color change since last use */
shrink_glyph_grey(g);
else if (fg_active != fg_current) /* if GCs need updating */
@@ -695,8 +685,6 @@ prescan(void)
nextreportpage = current_page;
}
- if (read_events(EV_NOWAIT) & EV_GE_NEWPAGE) break;
-
/* No calls to read_events() occur in this case. */
spcl_scan(scan_special);
@@ -808,8 +796,6 @@ load_n_set_char(wide_ubyte cmd, wide_ubyte ch)
#endif
{
if (!load_font(currinf.fontp)) { /* if not found */
- if (ev_flags & EV_GE_NEWDOC) /* if abort */
- longjmp(canit_env, 1);
Fputs("Character(s) will be left blank.\n", stderr);
currinf.set_char_p = currinf.fontp->set_char_p = set_empty_char;
#ifndef TEXXET
@@ -1324,19 +1310,7 @@ draw_page()
psfig_begun = False;
drawing_mag = (currwin.win == alt.win);
- /* NOTE: longjmp(canit_env) should not be done within read_events(). */
- if (!setjmp(canit_env))
- draw_part(current_frame = &frame0, dimconv);
- else { /* if interrupted */
- /* If we were interrupted, put the expose event back, so that the
- * region gets redrawn. The if statement is necessary because the
- * magnifier may have been destroyed as part of the interrupt. */
- if (currwin.win == mane.win || currwin.win == alt.win)
- expose(currwin.win == mane.win ? &mane : &alt,
- min_x - currwin.base_x, min_y - currwin.base_y,
- max_x - min_x, max_y - min_y);
- ev_flags &= ~EV_MAG_GONE;
- }
+ draw_part(current_frame = &frame0, dimconv);
drawing_mag = False;
dvi_pointer_frame = NULL;
diff --git a/events.c b/events.c
@@ -27,13 +27,9 @@ NOTE:
\*========================================================================*/
-#include <sys/wait.h> /* waitpid, WNOHANG */
-
#include <ctype.h>
-#include <errno.h>
#include <limits.h> /* abs() */
#include <math.h> /* pow() */
-#include <signal.h>
#include <stdlib.h> /* free(), atoi(), atof(), exit(), abs() */
#include <X11/Xatom.h>
@@ -54,10 +50,6 @@ NOTE:
#include "xdvi.h"
-#ifndef SIGPOLL
-#define SIGPOLL SIGIO
-#endif
-
#define MAGBORD 1 /* border size for magnifier */
/*
@@ -76,13 +68,11 @@ static Position mag_x, mag_y, new_mag_x, new_mag_y;
static int mag_conv_x, mag_conv_y;
static Boolean dragcurs = False;
-static sigset_t all_signals;
-
typedef void (*home_proc)(Boolean);
typedef void (*mouse_proc)(XEvent *);
+static void can_exposures(struct WindowRec *);
void null_mouse(XEvent *);
-static void xdvi_normal_exit();
mouse_proc mouse_motion = null_mouse;
mouse_proc mouse_release = null_mouse;
@@ -296,10 +286,6 @@ static short alt_stat; /* 1 = wait for expose, */
* Data for buffered events.
*/
-static volatile int event_freq = 70;
-static void can_exposures();
-
-
#define gamma resource._gamma
static void
@@ -525,7 +511,7 @@ do_color_change()
* Event-handling routines
*/
-void
+static void
expose(windowrec, x, y, w, h)
struct WindowRec *windowrec;
int x, y;
@@ -866,11 +852,7 @@ ACTION(Act_minus)
static
ACTION(Act_quit)
{
- if (debug & DBG_EVENT)
- puts(event_freq < 0
- ? "SIGPOLL is working"
- : "no SIGPOLL signals received");
- xdvi_normal_exit();
+ exit(1);
}
static
@@ -1626,180 +1608,6 @@ handle_messages(widget, closure, event, cont)
/*
- * Interrupt system for receiving events. The program sets a flag
- * whenever an event comes in, so that at the proper time (i.e., when
- * reading a new dvi item), we can check incoming events to see if we
- * still want to go on printing this page. This way, one can stop
- * displaying a page if it is about to be erased anyway. We try to read
- * as many events as possible before doing anything and base the next
- * action on all events read.
- * Note that the Xlib and Xt routines are not reentrant, so the most we
- * can do is set a flag in the interrupt routine and check it later.
- * Also, sometimes the interrupts are not generated (some systems only
- * guarantee that SIGIO is generated for terminal files, and on the system
- * I use, the interrupts are not generated if I use "(xdvi foo &)" instead
- * of "xdvi foo"). Therefore, there is also a mechanism to check the
- * event queue every 70 drawing operations or so. This mechanism is
- * disabled if it turns out that the interrupts do work.
- * For a fuller discussion of some of the above, see xlife in
- * comp.sources.x.
- */
-
-/*
- * Signal flags
- */
-
-/* This could be static volatile, but we want to avoid any optimizer bugs. */
-volatile unsigned int sig_flags = 0;
-
-#define SF_USR 1
-#define SF_ALRM 2
-#define SF_POLL 4
-#define SF_CHLD 8
-#define SF_TERM 16
-
-static void do_sigterm(void);
-static void do_sigchld(void);
-static void do_sigpoll(void);
-static void do_sigusr(void);
-
-#define SP0 do_sigusr /* these must be in the same order as SF_* */
-#define SP2 do_sigpoll
-#define SP3 do_sigchld
-#define SP4 do_sigterm /* highest priority */
-
-typedef void (*signalproc)(void);
-
-static const signalproc flags_to_sigproc[32]
- = {NULL, SP0, SP4, SP4, SP2, SP2, SP2, SP2,
- SP3, SP3, SP3, SP3, SP3, SP3, SP3, SP3,
- SP4, SP4, SP4, SP4, SP4, SP4, SP4, SP4,
- SP4, SP4, SP4, SP4, SP4, SP4, SP4, SP4};
-
-#undef SP0
-#undef SP2
-#undef SP3
-#undef SP4
-
-
-/*
- * Signal routines. At the signal level, all we do is set flags.
- */
-
-/* ARGSUSED */
-static void
-handle_sigpoll(signo)
- int signo;
-{
- event_counter = 1;
- event_freq = -1; /* forget Plan B */
- sig_flags |= SF_POLL;
-}
-
-/* ARGSUSED */
-static void
-handle_sigterm(signo)
- int signo;
-{
- sig_flags |= SF_TERM;
-}
-
-/* ARGSUSED */
-static void
-handle_sigchld(signo)
- int signo;
-{
- sig_flags |= SF_CHLD;
-}
-
-/* ARGSUSED */
-static void
-handle_sigalrm(signo)
- int signo;
-{
- sig_flags |= SF_ALRM;
-}
-
-/* ARGSUSED */
-static void
-handle_sigusr(signo)
- int signo;
-{
- event_counter = 1;
- sig_flags |= SF_USR;
-}
-
-
-/*
- * enable_intr() - Called from main to set up the signal handlers.
- */
-
-void
-enable_intr() {
- int sock_fd = ConnectionNumber(DISP);
- struct sigaction a;
-
- /* Subprocess handling, e.g., MakeTeXPK, fails on the Alpha without
- this, because SIGPOLL interrupts the call of system(3), since OSF/1
- doesn't retry interrupted wait calls by default. From code by
- maj@cl.cam.ac.uk. */
- a.sa_handler = handle_sigpoll;
- (void) sigemptyset(&a.sa_mask);
- (void) sigaddset(&a.sa_mask, SIGPOLL);
- a.sa_flags = SA_RESTART;
- sigaction(SIGPOLL, &a, NULL);
-
- prep_fd(sock_fd, False);
-
- a.sa_handler = handle_sigterm;
- (void) sigemptyset(&a.sa_mask);
- (void) sigaddset(&a.sa_mask, SIGINT);
- (void) sigaddset(&a.sa_mask, SIGQUIT);
- (void) sigaddset(&a.sa_mask, SIGTERM);
- (void) sigaddset(&a.sa_mask, SIGHUP);
- a.sa_flags = SA_RESETHAND;
- sigaction(SIGINT, &a, NULL);
- sigaction(SIGQUIT, &a, NULL);
- sigaction(SIGTERM, &a, NULL);
- sigaction(SIGHUP, &a, NULL);
-
- a.sa_handler = handle_sigchld;
- (void) sigemptyset(&a.sa_mask);
- (void) sigaddset(&a.sa_mask, SIGCHLD);
- a.sa_flags = 0;
- sigaction(SIGCHLD, &a, NULL);
-
- a.sa_handler = handle_sigalrm;
- (void) sigemptyset(&a.sa_mask);
- (void) sigaddset(&a.sa_mask, SIGALRM);
- a.sa_flags = 0;
- sigaction(SIGALRM, &a, NULL);
-
- a.sa_handler = handle_sigusr;
- (void) sigemptyset(&a.sa_mask);
- (void) sigaddset(&a.sa_mask, SIGUSR1);
- a.sa_flags = 0;
- sigaction(SIGUSR1, &a, NULL);
-
- (void) sigemptyset(&all_signals);
- (void) sigaddset(&all_signals, SIGPOLL);
- (void) sigaddset(&all_signals, SIGINT);
- (void) sigaddset(&all_signals, SIGQUIT);
- (void) sigaddset(&all_signals, SIGTERM);
- (void) sigaddset(&all_signals, SIGHUP);
- (void) sigaddset(&all_signals, SIGCHLD);
- (void) sigaddset(&all_signals, SIGALRM);
- (void) sigaddset(&all_signals, SIGUSR1);
-
-}
-
-
-/*
- * Mid-level signal handlers. These are called from within read_events(),
- * and do the actual work appropriate for the given signal.
- */
-
-/*
* Process-related routines. Call set_chld() to indicate that a given
* child process should be watched for when it terminates. Call
* clear_chld() to remove the process from the list. When the child
@@ -1833,43 +1641,6 @@ clear_chld(cp)
*cpp = cp->next;
}
-static void
-do_sigchld()
-{
- pid_t pid;
- int status;
-
- sig_flags &= ~SF_CHLD;
-
- for (;;) {
- pid = waitpid(-1, &status, WNOHANG);
- if (pid == 0) break;
-
- if (pid != -1) {
- struct xchild **cpp;
- struct xchild *cp;
-
- for (cpp = &child_recs;;) {
- cp = *cpp;
- if (cp == NULL)
- break;
- if (cp->pid == pid) {
- *cpp = cp->next; /* unlink it */
- (cp->proc)(status);
- break;
- }
- cpp = &cp->next;
- }
- break;
- }
-
- if (errno == EINTR) continue;
- if (errno == ECHILD) break;
- perror("xdvi: waitpid");
- break;
- }
-}
-
/*
* File-related routines. Call set_io() to indicate that a given fd
@@ -1932,122 +1703,8 @@ clear_io(ip)
io_dirty = True;
}
-static void
-do_sigpoll()
-{
- struct xio *ip;
-
- sig_flags &= ~SF_POLL;
-
- if (io_dirty) {
- struct pollfd *fp;
-
- if (num_fds > max_fds) {
- if (fds != NULL) free(fds);
- fds = xmalloc(num_fds * sizeof *fds);
- max_fds = num_fds;
- fds->fd = ConnectionNumber(DISP);
- fds->events = POLLIN;
- }
- fp = fds + 1;
- for (ip = iorecs; ip != NULL; ip = ip->next) {
- fp->fd = ip->fd;
- fp->events = ip->xio_events;
- ip->pfd = fp;
- ++fp;
- }
- io_dirty = False;
- }
-
- for (;;) {
- if (poll(fds + 1, num_fds - 1, 0) >= 0)
- break;
-
- if (errno != EAGAIN && errno != EINTR) {
- perror("xdvi: poll");
- return;
- }
- }
-
- for (ip = iorecs; ip != NULL; ip = ip->next) {
- int revents = ip->pfd->revents;
-
- if (revents & POLLIN) (ip->read_proc)();
- if (revents & POLLOUT) (ip->write_proc)();
- }
-}
-
-
-/*
- * Handle SIGUSR1 signal. Pretty straightforward.
- */
-
-static void
-do_sigusr()
-{
- sig_flags &= ~SF_USR;
- if (dvi_file != NULL) {
- Fclose(dvi_file);
- dvi_file = NULL;
- dvi_file_ready = False;
- }
- ev_flags |= EV_NEWDOC;
-}
-
-
-/*
- * Handle termination signals. Kill child processes, if permitted.
- * Otherwise, leave it up to the caller. This is the only place where
- * the EV_TERM event flag is set, and it can only happen if there's an
- * active non-killable process. This should only happen if read_events()
- * is called from one of a very few select locations.
- */
-
-static void
-do_sigterm()
-{
- struct xchild *cp;
- Boolean all_killed = True;
-
- sig_flags &= ~SF_TERM;
-
- /* loop through child processes */
- for (cp = child_recs; cp != NULL; cp = cp->next)
- if (cp->killable)
- kill(cp->pid, SIGKILL);
- else
- all_killed = False;
-
- if (all_killed) /* if all processes killed */
- exit(0);
-
- ev_flags |= EV_TERM; /* otherwise, let the caller handle it */
-}
-
-/*
- * Set the flag so that termination occurs, via the above routine.
- * This should be used in place of exit() when there may be a
- * non-killable process running (e.g., anytime within read_events()).
- */
-
-static void
-xdvi_normal_exit()
-{
- sig_flags |= SF_TERM;
-}
-
/*
- * Since redrawing the screen is (potentially) a slow task, xdvi checks
- * for incoming events while this is occurring. It does not register
- * a work proc that draws and returns every so often, as the toolkit
- * documentation suggests. Instead, it checks for events periodically
- * (or not, if SIGPOLL can be used instead) and processes them in
- * a subroutine called by the page drawing routine. This routine (below)
- * checks to see if anything has happened and processes those events and
- * signals. (Or, if it is called when there is no redrawing that needs
- * to be done, it blocks until something happens.)
- *
* Ultimately, the goal is to have this be the only place in xdvi where
* blocking occurs.
*
@@ -2059,123 +1716,26 @@ xdvi_normal_exit()
*/
unsigned int
-read_events(ret_mask)
- unsigned int ret_mask;
+read_events(unsigned int ret_mask)
{
XEvent event;
- for (;;) {
- event_counter = event_freq;
- /*
- * The above line clears the flag indicating that an event is
- * pending. So if an event comes in right now, the flag will be
- * set again needlessly, but we just end up making an extra call.
- * Also, be careful about destroying the magnifying glass while
- * drawing on it.
- */
-
- if (event_freq < 0) { /* if SIGPOLL works */
-
- if (!XtPending()) {
- sigset_t oldsig;
-
- (void) sigprocmask(SIG_BLOCK, &all_signals, &oldsig);
- for (;;) {
- while (sig_flags)
- flags_to_sigproc[sig_flags]();
-
- if (XtPending())
- break;
-
- if (ev_flags & ret_mask) {
- (void) sigprocmask(SIG_SETMASK, &oldsig,
- (sigset_t *) NULL);
- return ev_flags;
- }
- (void) sigsuspend(&oldsig);
- }
- (void) sigprocmask(SIG_SETMASK, &oldsig, (sigset_t *) NULL);
- }
- }
- else
- {
- for (;;) {
- struct xio *ip;
-
- while (sig_flags) {
- sigset_t oldsig;
-
- (void) sigprocmask(SIG_BLOCK, &all_signals, &oldsig);
-
- while (sig_flags)
- flags_to_sigproc[sig_flags]();
+ for(;;) {
- (void) sigprocmask(SIG_SETMASK, &oldsig,
- (sigset_t *) NULL);
- }
-
- if (XtPending())
- break;
-
- if (ev_flags & ret_mask)
+ if (!XtPending() && (ev_flags & ret_mask))
return ev_flags;
- /* If a SIGUSR1 signal comes right now, then it will wait
- until an X event or another SIGUSR1 signal arrives. */
-
- if (io_dirty) {
- struct pollfd *fp;
-
- if (num_fds > max_fds) {
- if (fds != NULL) free(fds);
- fds = xmalloc(num_fds * sizeof *fds);
- max_fds = num_fds;
- fds->fd = ConnectionNumber(DISP);
- fds->events = POLLIN;
- }
- fp = fds + 1;
- for (ip = iorecs; ip != NULL; ip = ip->next) {
- fp->fd = ip->fd;
- fp->events = ip->xio_events;
- ip->pfd = fp;
- ++fp;
- }
- io_dirty = False;
- }
+ XtNextEvent(&event);
- for (;;) {
- if (poll(fds, num_fds, -1) >= 0) {
- for (ip = iorecs; ip != NULL; ip = ip->next) {
- int revents = ip->pfd->revents;
-
- if (revents & POLLIN) (ip->read_proc)();
- if (revents & POLLOUT) (ip->write_proc)();
- }
- break;
- }
-
- if (errno == EINTR)
- break;
-
- if (errno != EAGAIN) {
- perror("xdvi: poll");
- break;
- }
- }
+ if (resized)
+ get_geom();
+ if (event.xany.window == alt.win && event.type == Expose) {
+ handle_expose((Widget) NULL, (XtPointer) &alt, &event,
+ (Boolean *) NULL);
+ continue;
}
- }
-
-
- XtNextEvent(&event);
- if (resized) get_geom();
- if (event.xany.window == alt.win && event.type == Expose) {
- handle_expose((Widget) NULL, (XtPointer) &alt, &event,
- (Boolean *) NULL);
- continue;
- }
- (void) XtDispatchEvent(&event);
-
+ XtDispatchEvent(&event);
}
}
diff --git a/events.h b/events.h
@@ -81,11 +81,9 @@ extern struct WindowRec mane, alt, currwin;
#define EV_NOWAIT EV_GE_IDLE
unsigned int ev_flags = EV_IDLE;
-volatile int event_counter = 0;
Bool compile_action(const char *, struct xdvi_action **);
-void expose(struct WindowRec *, int, int, unsigned int, unsigned int);
void do_color_change(void);
void do_pages(void) __attribute__((__noreturn__));
void enable_intr(void);
diff --git a/special.c b/special.c
@@ -1181,7 +1181,6 @@ color_special(cp)
scanned_page =
scanned_page_color = scanned_page_reset = -1;
ev_flags |= EV_NEWPAGE; /* force a redraw */
- longjmp(canit_env, 1);
}
return;
}
@@ -1362,7 +1361,6 @@ applicationDoSpecial(cp)
scanned_page =
scanned_page_color = scanned_page_reset = -1;
ev_flags |= EV_NEWPAGE; /* force a redraw */
- longjmp(canit_env, 1);
}
return;
}
@@ -1374,7 +1372,6 @@ applicationDoSpecial(cp)
scanned_page_color =
scanned_page_reset = -1;
ev_flags |= EV_NEWPAGE; /* force a redraw */
- longjmp(canit_env, 1);
}
return;
}
diff --git a/special.h b/special.h
@@ -1,9 +1,5 @@
-#include <setjmp.h>
-
#include "data.h" /* struct rgb */
-jmp_buf canit_env;
-
/*
* Used by the geometry-scanning routines.
* It passes pointers to routines to be called at certain
@@ -13,7 +9,6 @@ jmp_buf canit_env;
struct geom_info {
void (*geom_box) (struct geom_info *, long, long, long, long);
void (*geom_special) (struct geom_info *, const char *);
- jmp_buf done_env;
void *geom_data;
};
diff --git a/wdvi.1 b/wdvi.1
@@ -1012,14 +1012,6 @@ package, and the
environment in the
.B framed
La\*(Te\&2e package.
-.SH SIGNALS
-When
-.B wdvi
-receives a
-.SB SIGUSR1
-signal, it rereads the
-.I dvi
-file.
.SH ENVIRONMENT
.TP
.SB DISPLAY
diff --git a/xdvi.c b/xdvi.c
@@ -81,7 +81,7 @@ NOTE:
#include "default.h" /* default_dvi, default_dvi_len */
#include "dvi-init.h" /* init_dvi_file(), init_page() */
#include "dvi-draw.h" /* prescan() */
-#include "events.h" /* enable_intr(), compile_action(), ... */
+#include "events.h" /* compile_action(), ... */
#include "font-open.h" /* init_font_open() */
#include "util.h" /* xmalloc(), memicmp() */
#include "version.h"
@@ -873,8 +873,6 @@ main(int argc, char **argv)
if (visual->class != TrueColor)
errx(1, "X visual not 'TrueColor' is not supported.");
- enable_intr();
-
/*
* The default document is always available and simplifies startup
* by giving inital window sizes and no error popups.
@@ -883,7 +881,7 @@ main(int argc, char **argv)
err(1, "fmemopen");
dvi_name = "default.dvi";
ev_flags |= EV_NEWDOC;
- (void) read_events(EV_GE_NEWDOC);
+ read_events(EV_GE_NEWDOC);
ev_flags &= ~EV_NEWDOC;
if (resource.mfmode != NULL) {