This is an INCOMPLETE approach to the problem described at
http://bugs.debian.org/481123. As a result of this problem, urxvtcd
cannot any longer function as x-terminal-emulator on Debian systems.
There are a few problems with this patch, see below. I am sending it for
reference only. Under the above URL, there shall also be a log of the
discussion I had with Marc about these problems in a little while. It
could well be that urxvt is the only x-terminal-emulator alternative,
and that urxvtc should never be.
The solution extends the client-server protocol to enable the client
(urxvtc) to wait until the child (spawned by the server) returns. This
is implemented as follows:
1. If -wait is passed to the client, it sends 'WAIT' as sub-command to the
'NEW' command to the server.
Possible extension: send WAIT always when argv[0] is
'x-terminal-server', which is hard to do since urxvtcd hides
argv[0].
2. If the server receives 'WAIT', it sets the rxvt_term's finish_hook and
sends 'RUNNING' to the client.
3. Upon reception of 'RUNNING', the client just polls the socket in
anticipation of 'END' and thus stays around.
4. When the window is destroyed, rxvt_term::destroy_cb is called,
which in turn invokes the finish_hook (if set), thus informing the
client about the termination.
There are a couple of problems that need to be addressed:
- if the client process is killed, the window lives on
- command line parsing is broken/incomplete. Since only rxvtd knows
how to parse the entire command line, it needs to parse -wait, and
'WAIT' should not be sent.
- does all of this actually save us any resources?
Signed-off-by: martin f. krafft <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
src/main.C | 4 ++++
src/rxvt.h | 2 ++
src/rxvtc.C | 15 ++++++++++++++-
src/rxvtd.C | 22 +++++++++++++++++++++-
4 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/src/main.C b/src/main.C
index fd126ff..6cb168d 100644
--- a/src/main.C
+++ b/src/main.C
@@ -199,6 +199,8 @@ rxvt_term::rxvt_term ()
#ifdef KEYSYM_RESOURCE
keyboard = new keyboard_manager;
#endif
+
+ finish_hook = 0;
}
// clean up the most important stuff, do *not* call x or free mem etc.
@@ -355,6 +357,8 @@ rxvt_term::destroy_cb (ev::idle &w, int revents)
{
make_current ();
+ if (finish_hook) (*finish_hook) ();
+
delete this;
}
diff --git a/src/rxvt.h b/src/rxvt.h
index e19f201..23b7d14 100644
--- a/src/rxvt.h
+++ b/src/rxvt.h
@@ -657,6 +657,7 @@ typedef struct _mwmhints
typedef callback<void (const char *)> log_callback;
typedef callback<int (int)> getfd_callback;
+typedef callback<void ()> finish_callback;
/****************************************************************************/
@@ -968,6 +969,7 @@ struct rxvt_term : zero_initialized, rxvt_vars, rxvt_screen
log_callback *log_hook; // log error messages through this
hook, if != 0
getfd_callback *getfd_hook; // convert remote to local fd, if != 0
+ finish_callback *finish_hook; // notify daemon of term completion
#if ENABLE_PERL
rxvt_perl_term perl;
#endif
diff --git a/src/rxvtc.C b/src/rxvtc.C
index 7ca109e..1802014 100644
--- a/src/rxvtc.C
+++ b/src/rxvtc.C
@@ -109,8 +109,16 @@ main (int argc, const char *const *argv)
c.send ("ARG"), c.send ("-cd");
c.send ("ARG"), c.send (cwd);
+ bool wait = false;
+
for (int i = 1; i < argc; i++)
- c.send ("ARG"), c.send (argv[i]);
+ if (!strcmp (argv[i], "-wait")) {
+ wait = true;
+ c.send ("WAIT");
+ }
+ else {
+ c.send ("ARG"), c.send (argv[i]);
+ }
c.send ("END");
@@ -133,6 +141,11 @@ main (int argc, const char *const *argv)
exit (STATUS_FAILURE);
}
}
+ else if (!strcmp (tok, "RUNNING"))
+ {
+ // restart the loop in anticipation of END
+ continue;
+ }
else if (!strcmp (tok, "END"))
{
int success;
diff --git a/src/rxvtd.C b/src/rxvtd.C
index 5642827..f1f9089 100644
--- a/src/rxvtd.C
+++ b/src/rxvtd.C
@@ -42,16 +42,19 @@
struct server : rxvt_connection {
log_callback log_cb;
getfd_callback getfd_cb;
+ finish_callback finish_cb;
void read_cb (ev::io &w, int revents); ev::io read_ev;
void log_msg (const char *msg);
int getfd (int remote_fd);
+ void finish ();
server (int fd)
{
read_ev.set <server, &server::read_cb> (this);
log_cb.set <server, &server::log_msg> (this);
getfd_cb.set<server, &server::getfd> (this);
+ finish_cb.set<server, &server::finish> (this);
this->fd = fd;
fcntl (fd, F_SETFD, FD_CLOEXEC);
@@ -130,6 +133,11 @@ int server::getfd (int remote_fd)
return ptytty::recv_fd (fd);
}
+void server::finish ()
+{
+ send ("END"); send (1);
+}
+
void server::log_msg (const char *msg)
{
send ("MSG"), send (msg);
@@ -164,6 +172,7 @@ void server::read_cb (ev::io &w, int revents)
{
stringvec *argv = new stringvec;
stringvec *envv = new stringvec;
+ bool wait = false;
for (;;)
{
@@ -176,6 +185,8 @@ void server::read_cb (ev::io &w, int revents)
envv->push_back (strdup (tok));
else if (!strcmp (tok, "ARG") && recv (tok))
argv->push_back (strdup (tok));
+ else if (!strcmp (tok, "WAIT"))
+ wait = true;
else
return err ("protocol error: unexpected NEW token.\n");
}
@@ -206,7 +217,16 @@ void server::read_cb (ev::io &w, int revents)
if (!success)
term->destroy ();
- send ("END"); send (success ? 1 : 0);
+ if (success && wait) {
+ term->finish_hook = &finish_cb;
+ // END will be sent by the finish_hook, called from
+ // rxvt_term::destroy_cb, we send "RUNNING" to let the client
+ // know it should wait.
+ send ("RUNNING");
+ }
+ else {
+ send ("END"); send (success ? 1 : 0);
+ }
}
}
else
--
1.6.5.3
_______________________________________________
rxvt-unicode mailing list
[email protected]
http://lists.schmorp.de/cgi-bin/mailman/listinfo/rxvt-unicode