OK, I recently received a sysfs-fix.diff, which looks correct to me. I've fixed the problem in a different way though, on git.sf.net. My patches are larger, but they should waste less CPU time. The second one fixes a potential bug in the parser. I'll also make this the 0.8.1 release. Hope that works for debian^^
-------- Original Message -------- Subject: A thinkfan 0.8 bug and a patch Date: Sat, 14 Jul 2012 21:15:54 -0400 From: M. Vefa Bicakci <m....@runbox.com> To: mat...@lih.rwth-aachen.de Dear Victor Matare, I have found a bug in thinkfan 0.8 regarding the handling of sysfs files. I am using a 32-bit Debian Sid installation, up-to-date as of today, on a Thinkpad T420. In summary, instead of writing only the string form of an integer to a sysfs "pwm" fan control file, thinkfan 0.8 writes the string "level <integer>". As you will predict, this causes the kernel to report an error, which causes thinkfan to terminate. I am attaching a patch which fixes this issue. Even though the way I convert the level integer to a string is a bit crude, the patch fixes the bug. Thank you, M. Vefa Bicakci
Index: thinkfan-0.8.0/globaldefs.h =================================================================== --- thinkfan-0.8.0.orig/globaldefs.h 2012-05-10 14:37:34.000000000 -0400 +++ thinkfan-0.8.0/globaldefs.h 2012-07-14 20:54:27.188026323 -0400 @@ -95,7 +95,7 @@ struct tf_config *config; unsigned long int errcnt; -int *temps, tmax, last_tmax, lvl_idx, *b_tmax, line_count; +int *temps, tmax, last_tmax, cur_nlvl, lvl_idx, *b_tmax, line_count; unsigned int chk_sanity, watchdog_timeout, num_temps; char *config_file, *prefix, *rbuf, *cur_lvl, Index: thinkfan-0.8.0/system.c =================================================================== --- thinkfan-0.8.0.orig/system.c 2012-05-10 14:37:34.000000000 -0400 +++ thinkfan-0.8.0/system.c 2012-07-14 20:56:06.332031818 -0400 @@ -249,14 +249,20 @@ * Set fan speed (sysfs interface). ***********************************************************/ void setfan_sysfs() { - int fan, l = strlen(cur_lvl); + #define INT_STR_SIZE 128 + int fan, l; + char buf[INT_STR_SIZE]; - if (unlikely((fan = open(config->fan, O_WRONLY)) < 0)) { + if (unlikely((l = snprintf(buf, INT_STR_SIZE, "%d", cur_nlvl)) >= INT_STR_SIZE)) { + report(LOG_ERR, LOG_ERR, "%d is too large!\n", cur_nlvl); + errcnt++; + } + else if (unlikely((fan = open(config->fan, O_WRONLY)) < 0)) { report(LOG_ERR, LOG_ERR, "%s: %s\n", config->fan, strerror(errno)); errcnt++; } else { - if (unlikely(write(fan, cur_lvl, l) < l)) { + if (unlikely(write(fan, buf, l) < l)) { report(LOG_ERR, LOG_ERR, MSG_ERR_FANCTRL); errcnt++; } Index: thinkfan-0.8.0/thinkfan.c =================================================================== --- thinkfan-0.8.0.orig/thinkfan.c 2012-05-10 14:37:34.000000000 -0400 +++ thinkfan-0.8.0/thinkfan.c 2012-07-14 20:54:27.191026323 -0400 @@ -37,6 +37,7 @@ unsigned int sleeptime, tmp_sleeptime; #define set_fan cur_lvl = config->limits[lvl_idx].level; \ + cur_nlvl = config->limits[lvl_idx].nlevel; \ if (!quiet && nodaemon) \ report(LOG_DEBUG, LOG_DEBUG, MSG_DBG_T_STAT); \ config->setfan();
From 6de7d99e8cb95d15117454ffc5eea037bef54656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Matar=C3=A9?= <mat...@lih.rwth-aachen.de> Date: Fri, 10 Aug 2012 21:42:15 +0200 Subject: [PATCH 1/2] fix sysfs fan level string --- config.c | 9 ++++++--- globaldefs.h | 4 ++-- system.c | 3 ++- thinkfan.c | 3 +-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/config.c b/config.c index 9ccf794..2b34532 100644 --- a/config.c +++ b/config.c @@ -183,7 +183,7 @@ struct tf_config *readconfig(char* fname) { cfg_local->uninit_fan = uninit_fan_ibm; } - cur_lvl = cfg_local->limits[cfg_local->num_limits - 1].level; + lvl_idx = cfg_local->num_limits - 1; // configure sensor interface if (cfg_local->num_sensors > 0 && @@ -310,6 +310,8 @@ static int add_limit(struct tf_config *cfg, struct limit *limit) { long int tmp; char *end, *conv_lvl; + limit->sysfslevel = NULL; + // Check formatting of level string... tmp = strtol(limit->level, &end, 0); if (tmp < INT_MIN || tmp > INT_MAX) { @@ -324,13 +326,13 @@ static int add_limit(struct tf_config *cfg, struct limit *limit) { } else if (*end == 0) { // just a number + limit->sysfslevel = limit->level; conv_lvl = calloc(7 + strlen(limit->level), sizeof(char)); snprintf(conv_lvl, 7 + strlen(limit->level), "level %d", (int)tmp); - free(limit->level); limit->level = conv_lvl; limit->nlevel = (int)tmp; } - else if (sscanf(limit->level, "level %d", (int * )&tmp)) { + else if (sscanf(limit->level, "level %d", (int *)&tmp)) { limit->nlevel = (int)tmp; } else if (!strcmp(limit->level, "level disengaged") @@ -403,6 +405,7 @@ void free_config(struct tf_config *cfg) { } for (j=0; j < cfg->num_limits; j++) { free(cfg->limits[j].level); + free(cfg->limits[j].sysfslevel); free(cfg->limits[j].low); free(cfg->limits[j].high); } diff --git a/globaldefs.h b/globaldefs.h index c3b9fc2..99099bc 100644 --- a/globaldefs.h +++ b/globaldefs.h @@ -65,7 +65,8 @@ #define unlikely(x) __builtin_expect((x),0) struct limit { - char *level; // this is written to the fan control file. + char *level; // "level x" representation for /proc/acpi/ibm/fan. + char *sysfslevel; // numeric representation for /sys/class/hwmon int nlevel; // A numeric interpretation of the level int *low; // int array specifying the LOWER limit, terminated by INT_MIN int *high; // dito for UPPER limit. @@ -98,7 +99,6 @@ unsigned long int errcnt; int *temps, tmax, last_tmax, lvl_idx, *b_tmax, line_count; unsigned int chk_sanity, watchdog_timeout, num_temps; char *config_file, *prefix, *rbuf, - *cur_lvl, errmsg[1024], quiet, nodaemon, resume_is_safe, *oldpwm; // old contents of pwm*_enable, used for uninit_fan() diff --git a/system.c b/system.c index 7dfb3de..df4999d 100644 --- a/system.c +++ b/system.c @@ -109,6 +109,7 @@ int get_temps_ibm() { * Set fan speed (IBM interface). ***********************************************************/ void setfan_ibm() { + char *cur_lvl = config->limits[lvl_idx].level; int ibm_fan, l = strlen(cur_lvl); if (unlikely((ibm_fan = open(IBM_FAN, O_RDWR, O_TRUNC)) < 0)) { @@ -249,6 +250,7 @@ int get_temps_sysfs() { * Set fan speed (sysfs interface). ***********************************************************/ void setfan_sysfs() { + char *cur_lvl = config->limits[lvl_idx].sysfslevel; int fan, l = strlen(cur_lvl); if (unlikely((fan = open(config->fan, O_WRONLY)) < 0)) { @@ -322,7 +324,6 @@ void init_fan_sysfs() { if ((fd = open(fan_enable, O_WRONLY)) < 0) { report(LOG_ERR, LOG_ERR, "%s: %s\n", fan_enable, strerror(errno)); - free(fan_enable); errcnt |= ERR_FAN_INIT; goto fail; } diff --git a/thinkfan.c b/thinkfan.c index 4f627f1..31291f0 100644 --- a/thinkfan.c +++ b/thinkfan.c @@ -36,7 +36,7 @@ volatile int interrupted; unsigned int sleeptime, tmp_sleeptime; -#define set_fan cur_lvl = config->limits[lvl_idx].level; \ +#define set_fan \ if (!quiet && nodaemon) \ report(LOG_DEBUG, LOG_DEBUG, MSG_DBG_T_STAT); \ config->setfan(); @@ -184,7 +184,6 @@ int main(int argc, char **argv) { last_tmax = 0; tmax = 0; temps = NULL; - cur_lvl = NULL; openlog("thinkfan", LOG_CONS, LOG_USER); syslog(LOG_INFO, "thinkfan " VERSION " starting..."); -- 1.7.8.6
From 4a997a99bda24ba9815792513ffcaae39f4099bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Matar=C3=A9?= <mat...@lih.rwth-aachen.de> Date: Sat, 11 Aug 2012 00:19:41 +0200 Subject: [PATCH 2/2] parser.c: fix quotation parsing --- parser.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/parser.c b/parser.c index ab0c0c1..fff923b 100644 --- a/parser.c +++ b/parser.c @@ -311,7 +311,10 @@ char *parse_quotation(char **input, const char *mark) { int oldlc = line_count; start = *input; - if (!char_alt(input, mark, 0)) return NULL; + if (!char_alt(input, mark, 0)) { + *input = start; + return NULL; + } ret = char_cat(input, mark, 1); if (!ret) { ret = malloc(sizeof(char)); @@ -321,6 +324,7 @@ char *parse_quotation(char **input, const char *mark) { free(ret); ret = NULL; line_count = oldlc; + *input = start; } return ret; } -- 1.7.8.6
smime.p7s
Description: S/MIME Cryptographic Signature