emacsclient -t should not suspend Emacs server
* lisp.h, sysdep.c (block_tty_out_signal, unblock_tty_out_signal): New functions. * term.c (init_tty): Use them instead of rolling our own code. * sysdep.c (tcsetpgrp_without_stopping): Likewise. Here, this switches from 'signal' to 'pthread_sigmask', which is safer in multithreaded applications. * term.c (Fresume_tty): Don't bother dissociating if O_IGNORE_CTTY, which has already arranged for that. (dissociate_if_controlling_tty): If setsid fails, fall back on TIOCNOTTY. This is the main part of the bug fix. Fixes: debbugs:13387
This commit is contained in:
parent
a778dd57d0
commit
b895642720
4 changed files with 57 additions and 16 deletions
|
@ -1,3 +1,17 @@
|
|||
2013-01-11 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
emacsclient -t should not suspend Emacs server (Bug#13387)
|
||||
* lisp.h, sysdep.c (block_tty_out_signal, unblock_tty_out_signal):
|
||||
New functions.
|
||||
* term.c (init_tty): Use them instead of rolling our own code.
|
||||
* sysdep.c (tcsetpgrp_without_stopping): Likewise. Here, this
|
||||
switches from 'signal' to 'pthread_sigmask', which is safer in
|
||||
multithreaded applications.
|
||||
* term.c (Fresume_tty): Don't bother dissociating if O_IGNORE_CTTY,
|
||||
which has already arranged for that.
|
||||
(dissociate_if_controlling_tty): If setsid fails, fall back on TIOCNOTTY.
|
||||
This is the main part of the bug fix.
|
||||
|
||||
2013-01-10 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> (tiny change)
|
||||
|
||||
* gtkutil.c (xg_initialize): Add ifdef HAVE_FREETYPE around
|
||||
|
|
|
@ -3462,6 +3462,8 @@ extern void init_sigio (int);
|
|||
extern void sys_subshell (void);
|
||||
extern void sys_suspend (void);
|
||||
extern void discard_tty_input (void);
|
||||
extern void block_tty_out_signal (void);
|
||||
extern void unblock_tty_out_signal (void);
|
||||
extern void init_sys_modes (struct tty_display_info *);
|
||||
extern void reset_sys_modes (struct tty_display_info *);
|
||||
extern void init_all_sys_modes (void);
|
||||
|
|
26
src/sysdep.c
26
src/sysdep.c
|
@ -714,6 +714,27 @@ init_foreground_group (void)
|
|||
inherited_pgroup = getpid () == pgrp ? 0 : pgrp;
|
||||
}
|
||||
|
||||
/* Block and unblock SIGTTOU. */
|
||||
|
||||
void
|
||||
block_tty_out_signal (void)
|
||||
{
|
||||
#ifdef SIGTTOU
|
||||
sigset_t blocked;
|
||||
sigemptyset (&blocked);
|
||||
sigaddset (&blocked, SIGTTOU);
|
||||
pthread_sigmask (SIG_BLOCK, &blocked, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
unblock_tty_out_signal (void)
|
||||
{
|
||||
#ifdef SIGTTOU
|
||||
pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Safely set a controlling terminal FD's process group to PGID.
|
||||
If we are not in the foreground already, POSIX requires tcsetpgrp
|
||||
to deliver a SIGTTOU signal, which would stop us. This is an
|
||||
|
@ -725,11 +746,10 @@ static void
|
|||
tcsetpgrp_without_stopping (int fd, pid_t pgid)
|
||||
{
|
||||
#ifdef SIGTTOU
|
||||
signal_handler_t handler;
|
||||
block_input ();
|
||||
handler = signal (SIGTTOU, SIG_IGN);
|
||||
block_tty_out_signal ();
|
||||
tcsetpgrp (fd, pgid);
|
||||
signal (SIGTTOU, handler);
|
||||
unblock_tty_out_signal ();
|
||||
unblock_input ();
|
||||
#endif
|
||||
}
|
||||
|
|
31
src/term.c
31
src/term.c
|
@ -2423,7 +2423,7 @@ frame's terminal). */)
|
|||
if (fd == -1)
|
||||
error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
|
||||
|
||||
if (strcmp (t->display_info.tty->name, DEV_TTY))
|
||||
if (!O_IGNORE_CTTY && strcmp (t->display_info.tty->name, DEV_TTY) != 0)
|
||||
dissociate_if_controlling_tty (fd);
|
||||
|
||||
t->display_info.tty->output = fdopen (fd, "w+");
|
||||
|
@ -2903,13 +2903,23 @@ set_tty_hooks (struct terminal *terminal)
|
|||
terminal->delete_terminal_hook = &delete_tty;
|
||||
}
|
||||
|
||||
/* Drop the controlling terminal if fd is the same device. */
|
||||
/* If FD is the controlling terminal, drop it. */
|
||||
static void
|
||||
dissociate_if_controlling_tty (int fd)
|
||||
{
|
||||
pid_t pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
|
||||
if (0 <= pgid)
|
||||
setsid ();
|
||||
/* If tcgetpgrp succeeds, fd is the controlling terminal,
|
||||
so dissociate it by invoking setsid. */
|
||||
if (0 <= tcgetpgrp (fd) && setsid () < 0)
|
||||
{
|
||||
#ifdef TIOCNOTTY
|
||||
/* setsid failed, presumably because Emacs is already a process
|
||||
group leader. Fall back on the obsolescent way to dissociate
|
||||
a controlling tty. */
|
||||
block_tty_out_signal ();
|
||||
ioctl (fd, TIOCNOTTY, 0);
|
||||
unblock_tty_out_signal ();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a termcap display on the tty device with the given name and
|
||||
|
@ -3030,14 +3040,9 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
|
|||
|
||||
/* On some systems, tgetent tries to access the controlling
|
||||
terminal. */
|
||||
{
|
||||
sigset_t blocked;
|
||||
sigemptyset (&blocked);
|
||||
sigaddset (&blocked, SIGTTOU);
|
||||
pthread_sigmask (SIG_BLOCK, &blocked, 0);
|
||||
status = tgetent (tty->termcap_term_buffer, terminal_type);
|
||||
pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
|
||||
}
|
||||
block_tty_out_signal ();
|
||||
status = tgetent (tty->termcap_term_buffer, terminal_type);
|
||||
unblock_tty_out_signal ();
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue