reap off gpg processes

This commit is contained in:
Werner Koch 2001-02-13 15:00:31 +00:00
parent a3b341ff45
commit 962bb6af10
9 changed files with 120 additions and 17 deletions

View File

@ -1,5 +1,12 @@
2001-02-13 Werner Koch <wk@gnupg.org>
* rungpg.c (do_reaping,_gpgme_gpg_housecleaning): New.
(_gpgme_gpg_release): Reap children.
* io.h, posix-io.c (_gpgme_io_kill): New.
* w32-io.c (_gpgme_io_kill): New (dummy).
* keylist.c (gpgme_op_keylist_start): Cancel a pending request.
* posix-io.c (_gpgme_io_read): Add some debug output.
(_gpgme_io_write): Ditto.
(_gpgme_io_select): Increased the timeout.

View File

@ -51,6 +51,7 @@ int _gpgme_io_spawn ( const char *path, char **argv,
struct spawn_fd_item_s *fd_child_list,
struct spawn_fd_item_s *fd_parent_list );
int _gpgme_io_waitpid ( int pid, int hang, int *r_status, int *r_signal );
int _gpgme_io_kill ( int pid, int hard );
int _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds);

View File

@ -347,13 +347,24 @@ finish_key ( GpgmeCtx ctx )
/**
* gpgme_op_keylist_start:
* @c: context
* @pattern: a GnuPg user ID or NULL for all
* @secret_only: List only keys where the secret part is available
*
* Note that this function also cancels a pending key listing operaton..
*
* Return value: 0 on success or an errorcode.
**/
GpgmeError
gpgme_op_keylist_start ( GpgmeCtx c, const char *pattern, int secret_only )
{
GpgmeError rc = 0;
int i;
fail_on_pending_request( c );
if ( !c )
return mk_error (Invalid_Value);
c->pending = 1;
_gpgme_release_result (c);

View File

@ -206,6 +206,12 @@ _gpgme_io_waitpid ( int pid, int hang, int *r_status, int *r_signal )
return 0;
}
int
_gpgme_io_kill ( int pid, int hard )
{
return kill ( pid, hard? SIGKILL : SIGTERM );
}
/*
* Select on the list of fds.

View File

@ -37,6 +37,7 @@
#include "rungpg.h"
#include "context.h" /*temp hack until we have GpmeData methods to do I/O */
#include "io.h"
#include "sema.h"
#include "status-table.h"
@ -93,8 +94,6 @@ struct gpg_object_s {
int pid; /* we can't use pid_t because we don't use it in Windoze */
int running;
int exit_status;
int exit_signal;
/* stuff needed for pipemode */
struct {
@ -117,7 +116,17 @@ struct gpg_object_s {
} cmd;
};
static void kill_gpg ( GpgObject gpg );
struct reap_s {
struct reap_s *next;
pid_t pid;
time_t entered;
int term_send;
};
static struct reap_s *reap_list;
DEFINE_STATIC_LOCK (reap_list_lock);
static void free_argv ( char **argv );
static void free_fd_data_map ( struct fd_data_map_s *fd_data_map );
@ -217,25 +226,80 @@ _gpgme_gpg_release ( GpgObject gpg )
_gpgme_io_close (gpg->colon.fd[1]);
#endif
free_fd_data_map (gpg->fd_data_map);
kill_gpg (gpg); /* fixme: should be done asyncronously */
xfree (gpg);
if (gpg->running) {
int pid = gpg->pid;
struct reap_s *r;
/* resuse the memory, so that we don't need to allocate another
* mem block and have to handle errors */
assert (sizeof *r < sizeof *gpg );
r = (void*)gpg;
memset (r, 0, sizeof *r);
r->pid = pid;
r->entered = time (NULL);
LOCK(reap_list_lock);
r->next = reap_list;
reap_list = r;
UNLOCK(reap_list_lock);
}
else
xfree (gpg);
}
static void
kill_gpg ( GpgObject gpg )
do_reaping (void)
{
#if 0
if ( gpg->running ) {
/* still running? Must send a killer */
kill ( gpg->pid, SIGTERM);
sleep (2);
if ( !waitpid (gpg->pid, NULL, WNOHANG) ) {
/* pay the murderer better and then forget about it */
kill (gpg->pid, SIGKILL);
struct reap_s *r, *rlast;
static time_t last_check;
time_t cur_time = time (NULL);
/* a race does not matter here */
if (!last_check)
last_check = time(NULL);
if (last_check >= cur_time)
return; /* we check only every second */
/* fixme: it would be nice if to have a TRYLOCK here */
LOCK (reap_list_lock);
for (r=reap_list,rlast=NULL; r ; rlast=r, r=r?r->next:NULL) {
int dummy1, dummy2;
if ( _gpgme_io_waitpid (r->pid, 0, &dummy1, &dummy2) ) {
/* process has terminated - remove it from the queue */
void *p = r;
if (!rlast) {
reap_list = r->next;
r = reap_list;
}
else {
rlast->next = r->next;
r = rlast;
}
xfree (p);
}
else if ( !r->term_send ) {
if( r->entered+1 >= cur_time ) {
_gpgme_io_kill ( r->pid, 0);
r->term_send = 1;
r->entered = cur_time;
}
}
else {
/* give it 5 second before we are going to send the killer */
if ( r->entered+5 >= cur_time ) {
_gpgme_io_kill (r->pid, 1);
r->entered = cur_time; /* just in case we have to repat it */
}
}
gpg->running = 0;
}
#endif
UNLOCK (reap_list_lock);
}
void
_gpgme_gpg_housecleaning ()
{
do_reaping ();
}
void

View File

@ -95,6 +95,7 @@ typedef const char *(*GpgCommandHandler)(void*, GpgStatusCode code,
GpgmeError _gpgme_gpg_new ( GpgObject *r_gpg );
void _gpgme_gpg_release ( GpgObject gpg );
void _gpgme_gpg_housecleaning (void);
void _gpgme_gpg_enable_pipemode ( GpgObject gpg );
GpgmeError _gpgme_gpg_add_arg ( GpgObject gpg, const char *arg );
GpgmeError _gpgme_gpg_add_data ( GpgObject gpg, GpgmeData data, int dup_to );

View File

@ -598,6 +598,17 @@ _gpgme_io_waitpid ( int pid, int hang, int *r_status, int *r_signal )
return ret;
}
int
_gpgme_io_kill ( int pid, int hard )
{
HANDLE proc = fd_to_handle (pid);
#warning I am not sure how to kill a process
/* fixme: figure out how this can be done */
return 0;
}
/*
* Select on the list of fds.

View File

@ -323,6 +323,7 @@ gpgme_register_idle ( void (*fnc)(void) )
static void
run_idle ()
{
_gpgme_gpg_housecleaning ();
if (idle_function)
idle_function ();
}

View File

@ -64,6 +64,7 @@ main (int argc, char **argv )
do {
err = gpgme_new (&ctx);
fail_if_err (err);
gpgme_set_armor (ctx, 1);
err = gpgme_data_new_from_mem ( &in, "Hallo Leute\n", 12, 0 );
fail_if_err (err);