Skip to content

Commit

Permalink
ADDED: Prolog flag halt_grace_time: graceful timeout limit
Browse files Browse the repository at this point in the history
  • Loading branch information
JanWielemaker committed Oct 8, 2024
1 parent 7682c12 commit 9f07b39
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 9 deletions.
4 changes: 4 additions & 0 deletions man/overview.doc
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,10 @@ number support.
\prologflagitem{gui}{bool}{r}
Set to \const{true} if XPCE is around and can be used for graphics.

\prologflagitem{halt_grace_time}{float}{rw}
Time halt/1 waits for other threads to die gracefully. Default
is 1 second.

\prologflagitem{heartbeat}{integer}{rw}
If not zero, call prolog:heartbeat/0 every $N$ inferences. $N$ is
rounded to a multiple of 16.
Expand Down
1 change: 1 addition & 0 deletions src/ATOMS
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ A guard "guard"
A guard_in_caller "guard_in_caller"
A gvar "gvar"
A halt "halt"
A halt_grace_time "halt_grace_time"
A has_alternatives "has_alternatives"
A hash "hash"
A hashed "hashed"
Expand Down
1 change: 1 addition & 0 deletions src/os/pl-prologflag.c
Original file line number Diff line number Diff line change
Expand Up @@ -2047,6 +2047,7 @@ initPrologFlags(void)
truePrologFlag(PLFLAG_SIGNALS), PLFLAG_SIGNALS);
setPrologFlag("packs", FT_BOOL, GD->cmdline.packs, 0);
setPrologFlag("heartbeat", FT_INTEGER, (intptr_t)0);
setPrologFlag("halt_grace_time", FT_FLOAT, (double)1.0);

#if defined(__WINDOWS__) && defined(_DEBUG)
setPrologFlag("kernel_compile_mode", FT_ATOM|FF_READONLY, "debug");
Expand Down
48 changes: 39 additions & 9 deletions src/pl-thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
#include "pl-prims.h"
#include "pl-supervisor.h"
#include "pl-coverage.h"
#include "os/pl-prologflag.h"
#include <stdio.h>
#include <math.h>
#include <errno.h>
Expand Down Expand Up @@ -568,6 +569,7 @@ static void print_trace(int depth);
static void timespec_diff(struct timespec *diff,
const struct timespec *a, const struct timespec *b);
static int timespec_sign(const struct timespec *t);
static void timespec_add_double(struct timespec *ts, double tmo);

#undef LDFUNC_DECLARATIONS

Expand Down Expand Up @@ -1105,6 +1107,25 @@ dummy_handler(int sig)
}
#endif

static double
halt_grace_time(void)
{ GET_LD
fid_t fid;
term_t tmp;
double t;

if ( !( (fid=PL_open_foreign_frame()) &&
(tmp=PL_new_term_ref()) &&
PL_get_prolog_flag(ATOM_halt_grace_time, tmp) &&
PL_get_float(tmp, &t) ) )
t = 1.0;

if ( fid )
PL_discard_foreign_frame(fid);

return t;
}

int
exitPrologThreads(void)
{ int rc = true;
Expand Down Expand Up @@ -1170,13 +1191,16 @@ exitPrologThreads(void)
}

if ( canceled > 0 ) /* see (*) above */
{
{ double grace_time = halt_grace_time();

#ifdef USE_TIMER_WAIT
DEBUG(MSG_CLEANUP_THREAD, Sdprintf("Waiting for %d threads (alarm timer)\n", canceled));
struct itimerval timeout = {0};
struct sigaction act = {0};
double ip, fp=modf(grace_time,&ip);

timeout.it_value.tv_sec = 1;
timeout.it_value.tv_sec = (time_t)ip;
timeout.it_value.tv_nsec = (long)(fp*1000000000.0);
act.sa_handler = dummy_handler;

if ( sigaction(SIGALRM, &act, NULL) != 0 ||
Expand All @@ -1198,8 +1222,7 @@ exitPrologThreads(void)
struct timespec deadline;

get_current_timespec(&deadline);
deadline.tv_nsec += 1000000000; /* 1 sec */
carry_timespec_nanos(&deadline);
timespec_add_double(&deadline, grace_time);

while(canceled > 0)
{ if ( sem_timedwait(sem_canceled_ptr, &deadline) == 0 )
Expand Down Expand Up @@ -4928,6 +4951,16 @@ static const PL_option_t timeout_options[] =
false (leading to failure).
*/

static void
timespec_add_double(struct timespec *ts, double tmo)
{ double ip, fp=modf(tmo,&ip);

ts->tv_sec += (time_t)ip;
ts->tv_nsec += (long)(fp*1000000000.0);
carry_timespec_nanos(ts);
}


#define process_deadline_options(options, ts, pts, rs, prs) \
LDFUNC(process_deadline_options, options, ts, pts, rs, prs)

Expand Down Expand Up @@ -4978,11 +5011,8 @@ process_deadline_options(DECL_LD term_t options,
// was set to now + timeout.
if ( tmo != DBL_MAX )
{ if ( tmo > 0.0 )
{ double ip, fp=modf(tmo,&ip);

timeout.tv_sec = now.tv_sec + (time_t)ip;
timeout.tv_nsec = now.tv_nsec + (long)(fp*1000000000.0);
carry_timespec_nanos(&timeout);
{ timeout = now;
timespec_add_double(&timeout, tmo);
if ( dlop==NULL || timespec_cmp(&timeout,&deadline) < 0 )
dlop = &timeout;
} else if ( tmo == 0.0 )
Expand Down

0 comments on commit 9f07b39

Please sign in to comment.