Commit 24afd61775b957009619e0d3a5948492bdf5539e

Jeff Garzik 2011-03-18T17:24:16

Introduce more standardized logging (incl. optional syslog). Also, improve portability of alloca.

diff --git a/configure.ac b/configure.ac
index 8991cc4..e3d9df1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,6 +16,9 @@ AC_PROG_RANLIB
 
 dnl Checks for header files.
 AC_HEADER_STDC
+AC_CHECK_HEADERS(syslog.h)
+
+AC_FUNC_ALLOCA
 
 case $host in
   *-*-mingw*)
diff --git a/cpu-miner.c b/cpu-miner.c
index b521ea7..2b0ebe2 100644
--- a/cpu-miner.c
+++ b/cpu-miner.c
@@ -74,6 +74,7 @@ bool opt_debug = false;
 bool opt_protocol = false;
 bool want_longpoll = true;
 bool have_longpoll = false;
+bool use_syslog = false;
 static bool opt_quiet = false;
 static int opt_retries = 10;
 static int opt_fail_pause = 30;
@@ -88,6 +89,7 @@ struct thr_info *thr_info;
 static int work_thr_id;
 int longpoll_thr_id;
 struct work_restart *work_restart = NULL;
+pthread_mutex_t time_lock;
 
 
 struct option_help {
@@ -145,6 +147,11 @@ static struct option_help options_help[] = {
 	  "(-s N) Upper bound on time spent scanning current work,\n"
 	  "\tin seconds. (default: 5)" },
 
+#ifdef HAVE_SYSLOG_H
+	{ "syslog",
+	  "Use system log for output messages (default: standard error)" },
+#endif
+
 	{ "threads N",
 	  "(-t N) Number of miner threads (default: 1)" },
 
@@ -171,6 +178,11 @@ static struct option options[] = {
 	{ "url", 1, NULL, 1001 },
 	{ "userpass", 1, NULL, 1002 },
 	{ "no-longpoll", 0, NULL, 1003 },
+
+#ifdef HAVE_SYSLOG_H
+	{ "syslog", 0, NULL, 1004 },
+#endif
+
 	{ }
 };
 
@@ -240,13 +252,9 @@ static bool submit_upstream_work(CURL *curl, const struct work *work)
 {
 	char *hexstr = NULL;
 	json_t *val, *res;
-	char s[345], timestr[64];
-	time_t now;
-	struct tm *tm;
+	char s[345];
 	bool rc = false;
 
-	now = time(NULL);
-
 	/* build hex string */
 	hexstr = bin2hex(work->data, sizeof(work->data));
 	if (!hexstr) {
@@ -271,11 +279,8 @@ static bool submit_upstream_work(CURL *curl, const struct work *work)
 
 	res = json_object_get(val, "result");
 
-	tm = localtime(&now);
-	strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm);
-
-	printf("[%s] PROOF OF WORK RESULT: %s\n",
-	       timestr, json_is_true(res) ? "true (yay!!!)" : "false (booooo)");
+	applog(LOG_INFO, "PROOF OF WORK RESULT: %s",
+	       json_is_true(res) ? "true (yay!!!)" : "false (booooo)");
 
 	json_decref(val);
 
@@ -429,7 +434,7 @@ static void hashmeter(int thr_id, const struct timeval *diff,
 	secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0);
 
 	if (!opt_quiet)
-		printf("HashMeter(%d): %lu hashes, %.2f khash/sec\n",
+		applog(LOG_INFO, "thread %d: %lu hashes, %.2f khash/sec\n",
 		       thr_id, hashes_done,
 		       khashes / secs);
 }
@@ -625,7 +630,7 @@ static void *longpoll_thread(void *userdata)
 
 	sprintf(lp_url, "%s%s%s", rpc_url, need_slash ? "/" : "", copy_start);
 
-	fprintf(stderr, "Long-polling activated for %s\n", lp_url);
+	applog(LOG_INFO, "Long-polling activated for %s", lp_url);
 
 	curl = curl_easy_init();
 	if (!curl) {
@@ -641,7 +646,8 @@ static void *longpoll_thread(void *userdata)
 		if (val) {
 			failures = 0;
 			json_decref(val);
-			fprintf(stderr, "LONGPOLL detected new block\n");
+
+			applog(LOG_INFO, "LONGPOLL detected new block");
 			restart_threads();
 		} else {
 			if (failures++ < 10) {
@@ -764,6 +770,9 @@ static void parse_arg (int key, char *arg)
 	case 1003:
 		want_longpoll = false;
 		break;
+	case 1004:
+		use_syslog = true;
+		break;
 	default:
 		show_usage();
 	}
@@ -827,6 +836,13 @@ int main (int argc, char *argv[])
 	/* parse command line */
 	parse_cmdline(argc, argv);
 
+	pthread_mutex_init(&time_lock, NULL);
+
+#ifdef HAVE_SYSLOG_H
+	if (use_syslog)
+		openlog("cpuminer", LOG_PID, LOG_USER);
+#endif
+
 	/* set our priority to the highest (aka "nicest, least intrusive") */
 	if (setpriority(PRIO_PROCESS, 0, 19))
 		perror("setpriority");
@@ -887,7 +903,7 @@ int main (int argc, char *argv[])
 		sleep(1);	/* don't pound RPC server all at once */
 	}
 
-	fprintf(stderr, "%d miner threads started, "
+	applog(LOG_INFO, "%d miner threads started, "
 		"using SHA256 '%s' algorithm.\n",
 		opt_n_threads,
 		algo_names[opt_algo]);
@@ -895,7 +911,7 @@ int main (int argc, char *argv[])
 	/* main loop - simply wait for workio thread to exit */
 	pthread_join(thr_info[work_thr_id].pth, NULL);
 
-	fprintf(stderr, "workio thread dead, exiting.\n");
+	applog(LOG_INFO, "workio thread dead, exiting.");
 
 	return 0;
 }
diff --git a/miner.h b/miner.h
index dd32ee7..4021a69 100644
--- a/miner.h
+++ b/miner.h
@@ -8,6 +8,33 @@
 #include <jansson.h>
 #include <curl/curl.h>
 
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#elif defined __GNUC__
+# define alloca __builtin_alloca
+#elif defined _AIX
+# define alloca __alloca
+#elif defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+#else
+# ifndef HAVE_ALLOCA
+#  ifdef  __cplusplus
+extern "C"
+#  endif
+void *alloca (size_t);
+# endif
+#endif
+
+
 #ifdef __SSE2__
 #define WANT_SSE2_4WAY 1
 #endif
@@ -26,6 +53,14 @@
 #include <byteswap.h>
 #endif
 
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#else
+enum {
+	LOG_INFO,
+};
+#endif
+
 #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
 #undef unlikely
 #define unlikely(expr) (__builtin_expect((expr), 0))
@@ -126,10 +161,13 @@ struct work_restart {
 	char			padding[128 - sizeof(unsigned long)];
 };
 
+extern pthread_mutex_t time_lock;
+extern bool use_syslog;
 extern struct thr_info *thr_info;
 extern int longpoll_thr_id;
 extern struct work_restart *work_restart;
 
+extern void applog(int prio, const char *fmt, ...);
 extern struct thread_q *tq_new(void);
 extern void tq_free(struct thread_q *tq);
 extern bool tq_push(struct thread_q *tq, void *data);
diff --git a/util.c b/util.c
index 5b02e83..62cf422 100644
--- a/util.c
+++ b/util.c
@@ -14,9 +14,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
+#include <stdarg.h>
 #include <string.h>
 #include <jansson.h>
 #include <curl/curl.h>
+#include <time.h>
 #include "miner.h"
 #include "elist.h"
 
@@ -48,6 +50,47 @@ struct thread_q {
 	pthread_cond_t		cond;
 };
 
+void applog(int prio, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+
+#ifdef HAVE_SYSLOG_H
+	if (use_syslog) {
+		vsyslog(prio, fmt, ap);
+	}
+#else
+	if (0) {}
+#endif
+	else {
+		char *f;
+		int len;
+		struct timeval tv = { };
+		struct tm tm, *tm_p;
+
+		gettimeofday(&tv, NULL);
+
+		pthread_mutex_lock(&time_lock);
+		tm_p = localtime(&tv.tv_sec);
+		memcpy(&tm, tm_p, sizeof(tm));
+		pthread_mutex_unlock(&time_lock);
+
+		len = 40 + strlen(fmt) + 2;
+		f = alloca(len);
+		sprintf(f, "[%d-%02d-%02d %02d:%02d:%02d] %s\n",
+			tm.tm_year + 1900,
+			tm.tm_mon,
+			tm.tm_mday,
+			tm.tm_hour,
+			tm.tm_min,
+			tm.tm_sec,
+			fmt);
+		vfprintf(stderr, f, ap);	/* atomic write to stderr */
+	}
+	va_end(ap);
+}
+
 static void databuf_free(struct data_buffer *db)
 {
 	if (!db)