summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas 'Sortie' Termansen <sortie@maxsi.org>2014-08-29 09:42:41 -0700
committerJunio C Hamano <gitster@pobox.com>2014-08-29 12:25:28 -0700
commit0950f08806208b4e3d0aff5f4f7d497637ba4cab (patch)
tree44b527aef45080dafb1c051dbd12ee59fd18201c
parent710cdba60d50745bde8e86ff0b06490a4d24efcf (diff)
downloadgit-jt/timer-settime.tar.gz
use timer_settime() for new platformsjt/timer-settime
setitimer() is an obsolescent XSI interface and may be removed in a future standard. New applications should use the core POSIX timer_settime() instead. It's important that code doesn't simply check if timer_settime() is available as it can give false positives. Some systems like contemporary OpenBSD provides the function, but it unconditionally fails with ENOSYS at runtime. Clean up the progress reporting and change it to use timer_settime(), which will fall back to setitimer() automatically if timer_settime() is not supported. (see git-compat-util.h for how it does this). If both functions are not present, then git-compat-util.h provides replacements which will always fail with ENOSYS. The approach used here enables us to use a single API (timer_settime) without having to worry about checking for #ifdefs or if blocks which make it an unreadable nightmare. The major downside is for systems without timer_settime() support, they may fall back on a wrapped implementation which could have subtle differences. This should be a minor issue as almost all modern systems provide timer_settime() support. Note that this change means that git should never use setitimer() on its own now, as the fallback implementation of timer_settime() assumes that it is the sole user of ITIMER_REAL, and timer_delete() will reset the ITIMER_REAL. Signed-off-by: Jonas 'Sortie' Termansen <sortie@maxsi.org> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/log.c27
-rw-r--r--progress.c20
2 files changed, 33 insertions, 14 deletions
diff --git a/builtin/log.c b/builtin/log.c
index 4389722b4b..1eca66c62b 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -229,12 +229,13 @@ static void show_early_header(struct rev_info *rev, const char *stage, int nr)
printf(_("Final output: %d %s\n"), nr, stage);
}
-static struct itimerval early_output_timer;
+static timer_t early_output_timer;
static void log_show_early(struct rev_info *revs, struct commit_list *list)
{
int i = revs->early_output;
int show_header = 1;
+ struct itimerspec value;
sort_in_topological_order(&list, revs->sort_order);
while (list && i) {
@@ -271,9 +272,11 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list)
* trigger every second even if we're blocked on a
* reader!
*/
- early_output_timer.it_value.tv_sec = 0;
- early_output_timer.it_value.tv_usec = 500000;
- setitimer(ITIMER_REAL, &early_output_timer, NULL);
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_nsec = 500000L * 1000L;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_nsec = 0;
+ timer_settime(early_output_timer, 0, &value, NULL);
}
static void early_output(int signal)
@@ -284,6 +287,8 @@ static void early_output(int signal)
static void setup_early_output(struct rev_info *rev)
{
struct sigaction sa;
+ struct sigevent sev;
+ struct itimerspec value;
/*
* Set up the signal handler, minimally intrusively:
@@ -305,14 +310,22 @@ static void setup_early_output(struct rev_info *rev)
*
* This is a one-time-only trigger.
*/
- early_output_timer.it_value.tv_sec = 0;
- early_output_timer.it_value.tv_usec = 100000;
- setitimer(ITIMER_REAL, &early_output_timer, NULL);
+ memset(&sev, 0, sizeof(sev));
+ sev.sigev_notify = SIGEV_SIGNAL;
+ sev.sigev_signo = SIGALRM;
+ timer_create(CLOCK_MONOTONIC, &sev, &early_output_timer);
+
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_nsec = 100000L * 1000L;
+ value.it_interval.tv_sec = 0;
+ value.it_interval.tv_nsec = 0;
+ timer_settime(early_output_timer, 0, &value, NULL);
}
static void finish_early_output(struct rev_info *rev)
{
int n = estimate_commit_count(rev, rev->commits);
+ timer_delete(early_output_timer);
signal(SIGALRM, SIG_IGN);
show_early_header(rev, "done", n);
}
diff --git a/progress.c b/progress.c
index 412e6b1ecc..2321143db0 100644
--- a/progress.c
+++ b/progress.c
@@ -38,6 +38,7 @@ struct progress {
struct throughput *throughput;
};
+static timer_t progress_timer;
static volatile sig_atomic_t progress_update;
static void progress_interval(int signum)
@@ -48,7 +49,8 @@ static void progress_interval(int signum)
static void set_progress_signal(void)
{
struct sigaction sa;
- struct itimerval v;
+ struct sigevent sev;
+ struct itimerspec value;
progress_update = 0;
@@ -58,16 +60,20 @@ static void set_progress_signal(void)
sa.sa_flags = SA_RESTART;
sigaction(SIGALRM, &sa, NULL);
- v.it_interval.tv_sec = 1;
- v.it_interval.tv_usec = 0;
- v.it_value = v.it_interval;
- setitimer(ITIMER_REAL, &v, NULL);
+ memset(&sev, 0, sizeof(sev));
+ sev.sigev_notify = SIGEV_SIGNAL;
+ sev.sigev_signo = SIGALRM;
+ timer_create(CLOCK_MONOTONIC, &sev, &progress_timer);
+
+ value.it_interval.tv_sec = 1;
+ value.it_interval.tv_nsec = 0;
+ value.it_value = value.it_interval;
+ timer_settime(progress_timer, 0, &value, NULL);
}
static void clear_progress_signal(void)
{
- struct itimerval v = {{0,},};
- setitimer(ITIMER_REAL, &v, NULL);
+ timer_delete(progress_timer);
signal(SIGALRM, SIG_IGN);
progress_update = 0;
}