summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Dankov <tryagain@navit-project.org>2015-09-08 00:29:14 +0300
committerMichael Dankov <tryagain@navit-project.org>2015-09-08 00:29:14 +0300
commitccc7bc6c3503fe8e9e47afe853a3012ae2749f67 (patch)
tree05f9411c989221aa7cf4f62eed2f1e2c58ede639
parent6ea07f242cece8fb75f127fab732e934187b94fb (diff)
downloadnavit-ccc7bc6c3503fe8e9e47afe853a3012ae2749f67.tar.gz
Fix maptool SIGALRM handler
Use only asynchronous signal safe functions in SIGALRM handler. It was probably fprintf() causing random segfaults to maptool, which became very reproduceable after implementing progress report at phase 6.
-rw-r--r--navit/maptool/maptool.c107
1 files changed, 97 insertions, 10 deletions
diff --git a/navit/maptool/maptool.c b/navit/maptool/maptool.c
index e9c229494..cb16d9f74 100644
--- a/navit/maptool/maptool.c
+++ b/navit/maptool/maptool.c
@@ -72,16 +72,69 @@ int overlap=1;
int bytes_read;
static long start_brk;
-static struct timeval start_tv;
+static struct timespec start_ts;
+
+/*
+ Asynchronous signal safe lltoa function (note: no trailing \0 char!)
+*/
+int assafe_lltoa(long long n, int maxlen, char *buf)
+{
+ int i;
+ int out_length;
+
+ if(maxlen<1)
+ return 0;
+
+ if(n<0) {
+ n=-n;
+ buf[0]='-';
+ maxlen--;
+ buf++;
+ } else if(n==0) {
+ buf[0]='0';
+ return 1;
+ }
+
+ for(i=0; n>0 && i<maxlen; i++) {
+ buf[i]='0'+(n%10);
+ n/=10;
+ }
+ out_length=i;
+ for(i=0;i<out_length/2;i++) {
+ char c=buf[i];
+ buf[i]=buf[out_length-i-1];
+ buf[out_length-i-1]=c;
+ }
+ return out_length;
+}
+
+/*
+ Asynchronous signal safe string copy to buffer function (note: no trailing \0 char!)
+*/
+int assafe_strcp2buf(char *str, int maxlen, char *buf)
+{
+ int i;
+ for(i=0;str[i] && i<maxlen;i++)
+ buf[i]=str[i];
+ return i;
+}
static void
progress_time(void)
{
- struct timeval tv;
+ struct timespec ts;
int seconds;
- gettimeofday(&tv, NULL);
- seconds=tv.tv_sec-start_tv.tv_sec;
- fprintf(stderr," %d:%02d",seconds/60,seconds%60);
+ const int buflen=20;
+ char buf[buflen];
+ int pos=1;
+ buf[0]=' ';
+ clock_gettime(CLOCK_REALTIME, &ts);
+ seconds=ts.tv_sec-start_ts.tv_sec;
+ pos+=assafe_lltoa(seconds/60, buflen-pos, buf+pos);
+ seconds%=60;
+ pos+=assafe_strcp2buf(seconds>9?":":":0", buflen-pos, buf+pos);
+ pos+=assafe_lltoa(seconds, buflen-pos, buf+pos);
+ write(2,buf,pos);
}
static void
@@ -89,21 +142,54 @@ progress_memory(void)
{
#ifdef HAVE_SBRK
long mem=(long)sbrk(0)-start_brk;
- fprintf(stderr," %ld MB",mem/1024/1024);
+ const int buflen=20;
+ char buf[buflen];
+ int pos=1;
+ buf[0]=' ';
+ pos+=assafe_lltoa(mem/1024/1024, buflen-pos, buf+pos);
+ pos+=assafe_strcp2buf(" MB", buflen-pos, buf+pos);
+ write(2,buf,pos);
#endif
}
void
sig_alrm(int sig)
{
+ fflush(stderr);
+ sig_alrm_do(sig);
+}
+
+void
+sig_alrm_do(int sig)
+{
+ const int buflen=1024;
+ char buf[buflen];
+ int pos=0;
#ifndef _WIN32
- signal(SIGALRM, sig_alrm);
+ signal(SIGALRM, sig_alrm_do);
alarm(30);
#endif
- fprintf(stderr,"PROGRESS%d: Processed %d nodes (%d out) %d ways %d relations %d tiles", phase, processed_nodes, processed_nodes_out, processed_ways, processed_relations, processed_tiles);
+ pos+=assafe_strcp2buf("PROGRESS", buflen-pos, buf+pos);
+ pos+=assafe_lltoa(phase, buflen-pos, buf+pos);
+ pos+=assafe_strcp2buf(": Processed ", buflen-pos, buf+pos);
+ pos+=assafe_lltoa(processed_nodes, buflen-pos, buf+pos);
+ pos+=assafe_strcp2buf(" nodes (", buflen-pos, buf+pos);
+ pos+=assafe_lltoa(processed_nodes_out, buflen-pos, buf+pos);
+ pos+=assafe_strcp2buf(" out) ", buflen-pos, buf+pos);
+ pos+=assafe_lltoa(processed_ways, buflen-pos, buf+pos);
+ pos+=assafe_strcp2buf(" ways ", buflen-pos, buf+pos);
+ pos+=assafe_lltoa(processed_relations, buflen-pos, buf+pos);
+ pos+=assafe_strcp2buf(" relations ", buflen-pos, buf+pos);
+ pos+=assafe_lltoa(processed_tiles, buflen-pos, buf+pos);
+ pos+=assafe_strcp2buf(" tiles", buflen-pos, buf+pos);
+ write(2,buf,pos);
progress_time();
progress_memory();
- fprintf(stderr,"\n");
+#ifndef _WIN32
+ write(2,"\r\n",2);
+#else
+ write(2,"\n",1);
+#endif
}
@@ -444,6 +530,7 @@ start_phase(struct maptool_params *p, char *str)
phase++;
if (p->start <= phase && p->end >= phase) {
fprintf(stderr,"PROGRESS: Phase %d: %s",phase,str);
+ fflush(stderr);
progress_time();
progress_memory();
fprintf(stderr,"\n");
@@ -848,7 +935,7 @@ int main(int argc, char **argv)
#ifdef HAVE_SBRK
start_brk=(long)sbrk(0);
#endif
- gettimeofday(&start_tv, NULL);
+ clock_gettime(CLOCK_REALTIME, &start_ts);
while (1) {
int parse_result=parse_option(&p, argv, argc, &option_index);