diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-08-12 21:33:06 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-08-12 21:33:06 +0000 |
commit | 5f1b149d541ebba7cab841cb647f113248f9fb8f (patch) | |
tree | e7f962fba89b6e201b4c857e32d85c9671b3db0d /sysklogd | |
parent | 1b9064d5355b5c26676e8447a1900116066e42e4 (diff) | |
download | busybox-w32-5f1b149d541ebba7cab841cb647f113248f9fb8f.tar.gz busybox-w32-5f1b149d541ebba7cab841cb647f113248f9fb8f.tar.bz2 busybox-w32-5f1b149d541ebba7cab841cb647f113248f9fb8f.zip |
syslogd,logread: get rid of head pointer, fix logread bug in the process
function old new delta
logread_main 450 462 +12
syslogd_main 1246 1252 +6
shbuf - 4 +4
buf 34 30 -4
packed_usage 22729 22724 -5
log_locally 957 767 -190
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/3 up/down: 22/-199) Total: -177 bytes
text data bss dec hex filename
773886 1116 11316 786318 bff8e busybox_old
773714 1116 11316 786146 bfee2 busybox_unstripped
Diffstat (limited to 'sysklogd')
-rw-r--r-- | sysklogd/logread.c | 113 | ||||
-rw-r--r-- | sysklogd/syslogd.c | 55 |
2 files changed, 81 insertions, 87 deletions
diff --git a/sysklogd/logread.c b/sysklogd/logread.c index ac354b5c3..597e285a5 100644 --- a/sysklogd/logread.c +++ b/sysklogd/logread.c | |||
@@ -19,11 +19,10 @@ | |||
19 | enum { KEY_ID = 0x414e4547 }; /* "GENA" */ | 19 | enum { KEY_ID = 0x414e4547 }; /* "GENA" */ |
20 | 20 | ||
21 | static struct shbuf_ds { | 21 | static struct shbuf_ds { |
22 | int32_t size; // size of data written | 22 | int32_t size; // size of data - 1 |
23 | int32_t head; // start of message list | ||
24 | int32_t tail; // end of message list | 23 | int32_t tail; // end of message list |
25 | char data[1]; // data/messages | 24 | char data[1]; // messages |
26 | } *buf; // shared memory pointer | 25 | } *shbuf; |
27 | 26 | ||
28 | // Semaphore operation structures | 27 | // Semaphore operation structures |
29 | static struct sembuf SMrup[1] = {{0, -1, IPC_NOWAIT | SEM_UNDO}}; // set SMrup | 28 | static struct sembuf SMrup[1] = {{0, -1, IPC_NOWAIT | SEM_UNDO}}; // set SMrup |
@@ -34,7 +33,7 @@ static void error_exit(const char *str) ATTRIBUTE_NORETURN; | |||
34 | static void error_exit(const char *str) | 33 | static void error_exit(const char *str) |
35 | { | 34 | { |
36 | //release all acquired resources | 35 | //release all acquired resources |
37 | shmdt(buf); | 36 | shmdt(shbuf); |
38 | bb_perror_msg_and_die(str); | 37 | bb_perror_msg_and_die(str); |
39 | } | 38 | } |
40 | 39 | ||
@@ -50,7 +49,7 @@ static void sem_up(int semid) | |||
50 | static void interrupted(int sig ATTRIBUTE_UNUSED) | 49 | static void interrupted(int sig ATTRIBUTE_UNUSED) |
51 | { | 50 | { |
52 | signal(SIGINT, SIG_IGN); | 51 | signal(SIGINT, SIG_IGN); |
53 | shmdt(buf); | 52 | shmdt(shbuf); |
54 | exit(0); | 53 | exit(0); |
55 | } | 54 | } |
56 | 55 | ||
@@ -66,79 +65,105 @@ int logread_main(int argc, char **argv) | |||
66 | if (log_shmid == -1) | 65 | if (log_shmid == -1) |
67 | bb_perror_msg_and_die("can't find syslogd buffer"); | 66 | bb_perror_msg_and_die("can't find syslogd buffer"); |
68 | 67 | ||
69 | // Attach shared memory to our char* | 68 | /* Attach shared memory to our char* */ |
70 | buf = shmat(log_shmid, NULL, SHM_RDONLY); | 69 | shbuf = shmat(log_shmid, NULL, SHM_RDONLY); |
71 | if (buf == NULL) | 70 | if (shbuf == NULL) |
72 | bb_perror_msg_and_die("can't access syslogd buffer"); | 71 | bb_perror_msg_and_die("can't access syslogd buffer"); |
73 | 72 | ||
74 | log_semid = semget(KEY_ID, 0, 0); | 73 | log_semid = semget(KEY_ID, 0, 0); |
75 | if (log_semid == -1) | 74 | if (log_semid == -1) |
76 | error_exit("can't get access to semaphores for syslogd buffer"); | 75 | error_exit("can't get access to semaphores for syslogd buffer"); |
77 | 76 | ||
78 | // attempt to redefine ^C signal | ||
79 | signal(SIGINT, interrupted); | 77 | signal(SIGINT, interrupted); |
80 | 78 | ||
81 | // Suppose atomic memory move | 79 | /* Suppose atomic memory read */ |
82 | cur = follow ? buf->tail : buf->head; | 80 | /* Max possible value for tail is shbuf->size - 1 */ |
81 | cur = shbuf->tail; | ||
83 | 82 | ||
83 | /* Loop for logread -f, one pass if there was no -f */ | ||
84 | do { | 84 | do { |
85 | unsigned shbuf_size; | ||
86 | unsigned shbuf_tail; | ||
87 | const char *shbuf_data; | ||
85 | #if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING | 88 | #if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING |
86 | char *buf_data; | 89 | int i; |
87 | int log_len, j; | 90 | int len_first_part; |
91 | int len_total = len_total; /* for gcc */ | ||
92 | char *copy = copy; /* for gcc */ | ||
88 | #endif | 93 | #endif |
89 | if (semop(log_semid, SMrdn, 2) == -1) | 94 | if (semop(log_semid, SMrdn, 2) == -1) |
90 | error_exit("semop[SMrdn]"); | 95 | error_exit("semop[SMrdn]"); |
91 | 96 | ||
92 | if (DEBUG) | 97 | /* Copy the info, helps gcc to realize that it doesn't change */ |
93 | printf("head:%i cur:%d tail:%i size:%i\n", | 98 | shbuf_size = shbuf->size; |
94 | buf->head, cur, buf->tail, buf->size); | 99 | shbuf_tail = shbuf->tail; |
100 | shbuf_data = shbuf->data; /* pointer! */ | ||
95 | 101 | ||
96 | if (buf->head == buf->tail || cur == buf->tail) { | 102 | if (DEBUG) |
97 | if (follow) { | 103 | printf("cur:%d tail:%i size:%i\n", |
104 | cur, shbuf_tail, shbuf_size); | ||
105 | |||
106 | if (!follow) { | ||
107 | /* advance to oldest complete message */ | ||
108 | /* find NUL */ | ||
109 | cur += strlen(shbuf_data + cur); | ||
110 | if (cur >= shbuf_size) { /* last byte in buffer? */ | ||
111 | cur = strnlen(shbuf_data, shbuf_tail); | ||
112 | if (cur == shbuf_tail) | ||
113 | goto unlock; /* no complete messages */ | ||
114 | } | ||
115 | /* advance to first byte of the message */ | ||
116 | cur++; | ||
117 | if (cur >= shbuf_size) /* last byte in buffer? */ | ||
118 | cur = 0; | ||
119 | } else { /* logread -f */ | ||
120 | if (cur == shbuf_tail) { | ||
98 | sem_up(log_semid); | 121 | sem_up(log_semid); |
99 | fflush(stdout); | 122 | fflush(stdout); |
100 | sleep(1); /* TODO: replace me with a sleep_on */ | 123 | sleep(1); /* TODO: replace me with a sleep_on */ |
101 | continue; | 124 | continue; |
102 | } | 125 | } |
103 | puts("<empty syslog>"); | ||
104 | } | 126 | } |
105 | 127 | ||
106 | // Read Memory | 128 | /* Read from cur to tail */ |
107 | #if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING | 129 | #if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING |
108 | log_len = buf->tail - cur; | 130 | len_first_part = len_total = shbuf_tail - cur; |
109 | if (log_len < 0) | 131 | if (len_total < 0) { |
110 | log_len += buf->size; | 132 | /* message wraps: */ |
111 | buf_data = xmalloc(log_len); | 133 | /* [SECOND PART.........FIRST PART] */ |
112 | 134 | /* ^data ^tail ^cur ^size */ | |
113 | if (buf->tail >= cur) | 135 | len_total += shbuf_size; |
114 | j = log_len; | 136 | } |
115 | else | 137 | copy = xmalloc(len_total + 1); |
116 | j = buf->size - cur; | 138 | if (len_first_part < 0) { |
117 | memcpy(buf_data, buf->data + cur, j); | 139 | /* message wraps (see above) */ |
118 | 140 | len_first_part = shbuf_size - cur; | |
119 | if (buf->tail < cur) | 141 | memcpy(copy + len_first_part, shbuf_data, shbuf_tail); |
120 | memcpy(buf_data + buf->size - cur, buf->data, buf->tail); | 142 | } |
121 | cur = buf->tail; | 143 | memcpy(copy, shbuf_data + cur, len_first_part); |
144 | copy[len_total] = '\0'; | ||
145 | cur = shbuf_tail; | ||
122 | #else | 146 | #else |
123 | while (cur != buf->tail) { | 147 | while (cur != shbuf_tail) { |
124 | fputs(buf->data + cur, stdout); | 148 | fputs(shbuf_data + cur, stdout); |
125 | cur += strlen(buf->data + cur) + 1; | 149 | cur += strlen(shbuf_data + cur) + 1; |
126 | if (cur >= buf->size) | 150 | if (cur >= shbuf_size) |
127 | cur = 0; | 151 | cur = 0; |
128 | } | 152 | } |
129 | #endif | 153 | #endif |
130 | // release the lock on the log chain | 154 | unlock: |
155 | /* release the lock on the log chain */ | ||
131 | sem_up(log_semid); | 156 | sem_up(log_semid); |
132 | 157 | ||
133 | #if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING | 158 | #if ENABLE_FEATURE_LOGREAD_REDUCED_LOCKING |
134 | for (j = 0; j < log_len; j += strlen(buf_data+j) + 1) { | 159 | for (i = 0; i < len_total; i += strlen(copy + i) + 1) { |
135 | fputs(buf_data + j, stdout); | 160 | fputs(copy + i, stdout); |
136 | } | 161 | } |
137 | free(buf_data); | 162 | free(copy); |
138 | #endif | 163 | #endif |
139 | } while (follow); | 164 | } while (follow); |
140 | 165 | ||
141 | shmdt(buf); | 166 | shmdt(shbuf); |
142 | 167 | ||
143 | fflush_stdout_and_exit(EXIT_SUCCESS); | 168 | fflush_stdout_and_exit(EXIT_SUCCESS); |
144 | } | 169 | } |
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 0ed16bc9e..6ecbd16f0 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c | |||
@@ -46,8 +46,7 @@ enum { MAX_READ = 256 }; | |||
46 | 46 | ||
47 | /* Semaphore operation structures */ | 47 | /* Semaphore operation structures */ |
48 | struct shbuf_ds { | 48 | struct shbuf_ds { |
49 | int32_t size; /* size of data written */ | 49 | int32_t size; /* size of data - 1 */ |
50 | int32_t head; /* start of message list */ | ||
51 | int32_t tail; /* end of message list */ | 50 | int32_t tail; /* end of message list */ |
52 | char data[1]; /* data/messages */ | 51 | char data[1]; /* data/messages */ |
53 | }; | 52 | }; |
@@ -212,8 +211,9 @@ static void ipcsyslog_init(void) | |||
212 | bb_perror_msg_and_die("shmat"); | 211 | bb_perror_msg_and_die("shmat"); |
213 | } | 212 | } |
214 | 213 | ||
215 | G.shbuf->size = G.shm_size - offsetof(struct shbuf_ds, data); | 214 | memset(G.shbuf, 0, G.shm_size); |
216 | G.shbuf->head = G.shbuf->tail = 0; | 215 | G.shbuf->size = G.shm_size - offsetof(struct shbuf_ds, data) - 1; |
216 | /*G.shbuf->tail = 0;*/ | ||
217 | 217 | ||
218 | // we'll trust the OS to set initial semval to 0 (let's hope) | 218 | // we'll trust the OS to set initial semval to 0 (let's hope) |
219 | G.s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023); | 219 | G.s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023); |
@@ -231,7 +231,6 @@ static void ipcsyslog_init(void) | |||
231 | static void log_to_shmem(const char *msg, int len) | 231 | static void log_to_shmem(const char *msg, int len) |
232 | { | 232 | { |
233 | int old_tail, new_tail; | 233 | int old_tail, new_tail; |
234 | char *c; | ||
235 | 234 | ||
236 | if (semop(G.s_semid, G.SMwdn, 3) == -1) { | 235 | if (semop(G.s_semid, G.SMwdn, 3) == -1) { |
237 | bb_perror_msg_and_die("SMwdn"); | 236 | bb_perror_msg_and_die("SMwdn"); |
@@ -240,49 +239,20 @@ static void log_to_shmem(const char *msg, int len) | |||
240 | /* Circular Buffer Algorithm: | 239 | /* Circular Buffer Algorithm: |
241 | * -------------------------- | 240 | * -------------------------- |
242 | * tail == position where to store next syslog message. | 241 | * tail == position where to store next syslog message. |
243 | * head == position of next message to retrieve ("print"). | 242 | * tail's max value is (shbuf->size - 1) |
244 | * if head == tail, there is no "unprinted" messages left. | 243 | * Last byte of buffer is never used and remains NUL. |
245 | * head is typically advanced by separate "reader" program, | ||
246 | * but if there isn't one, we have to do it ourself. | ||
247 | * messages are NUL-separated. | ||
248 | */ | 244 | */ |
249 | len++; /* length with NUL included */ | 245 | len++; /* length with NUL included */ |
250 | again: | 246 | again: |
251 | old_tail = G.shbuf->tail; | 247 | old_tail = G.shbuf->tail; |
252 | new_tail = old_tail + len; | 248 | new_tail = old_tail + len; |
253 | if (new_tail < G.shbuf->size) { | 249 | if (new_tail < G.shbuf->size) { |
254 | /* No need to move head if shbuf->head <= old_tail, | ||
255 | * else... */ | ||
256 | if (old_tail < G.shbuf->head && G.shbuf->head <= new_tail) { | ||
257 | /* ...need to move head forward */ | ||
258 | c = memchr(G.shbuf->data + new_tail, '\0', | ||
259 | G.shbuf->size - new_tail); | ||
260 | if (!c) /* no NUL ahead of us, wrap around */ | ||
261 | c = memchr(G.shbuf->data, '\0', old_tail); | ||
262 | if (!c) { /* still nothing? point to this msg... */ | ||
263 | G.shbuf->head = old_tail; | ||
264 | } else { | ||
265 | /* convert pointer to offset + skip NUL */ | ||
266 | G.shbuf->head = c - G.shbuf->data + 1; | ||
267 | } | ||
268 | } | ||
269 | /* store message, set new tail */ | 250 | /* store message, set new tail */ |
270 | memcpy(G.shbuf->data + old_tail, msg, len); | 251 | memcpy(G.shbuf->data + old_tail, msg, len); |
271 | G.shbuf->tail = new_tail; | 252 | G.shbuf->tail = new_tail; |
272 | } else { | 253 | } else { |
273 | /* we need to break up the message and wrap it around */ | ||
274 | /* k == available buffer space ahead of old tail */ | 254 | /* k == available buffer space ahead of old tail */ |
275 | int k = G.shbuf->size - old_tail - 1; | 255 | int k = G.shbuf->size - old_tail; |
276 | if (G.shbuf->head > old_tail) { | ||
277 | /* we are going to overwrite head, need to | ||
278 | * move it out of the way */ | ||
279 | c = memchr(G.shbuf->data, '\0', old_tail); | ||
280 | if (!c) { /* nothing? point to this msg... */ | ||
281 | G.shbuf->head = old_tail; | ||
282 | } else { /* convert pointer to offset + skip NUL */ | ||
283 | G.shbuf->head = c - G.shbuf->data + 1; | ||
284 | } | ||
285 | } | ||
286 | /* copy what fits to the end of buffer, and repeat */ | 256 | /* copy what fits to the end of buffer, and repeat */ |
287 | memcpy(G.shbuf->data + old_tail, msg, k); | 257 | memcpy(G.shbuf->data + old_tail, msg, k); |
288 | msg += k; | 258 | msg += k; |
@@ -294,7 +264,7 @@ static void log_to_shmem(const char *msg, int len) | |||
294 | bb_perror_msg_and_die("SMwup"); | 264 | bb_perror_msg_and_die("SMwup"); |
295 | } | 265 | } |
296 | if (DEBUG) | 266 | if (DEBUG) |
297 | printf("head:%d tail:%d\n", G.shbuf->head, G.shbuf->tail); | 267 | printf("tail:%d\n", G.shbuf->tail); |
298 | } | 268 | } |
299 | #else | 269 | #else |
300 | void ipcsyslog_cleanup(void); | 270 | void ipcsyslog_cleanup(void); |
@@ -339,11 +309,10 @@ static void log_locally(char *msg) | |||
339 | } | 309 | } |
340 | #if ENABLE_FEATURE_ROTATE_LOGFILE | 310 | #if ENABLE_FEATURE_ROTATE_LOGFILE |
341 | { | 311 | { |
342 | struct stat statf; | 312 | struct stat statf; |
343 | 313 | G.isRegular = (fstat(G.logFD, &statf) == 0 && S_ISREG(statf.st_mode)); | |
344 | G.isRegular = (fstat(G.logFD, &statf) == 0 && (statf.st_mode & S_IFREG)); | 314 | /* bug (mostly harmless): can wrap around if file > 4gb */ |
345 | /* bug (mostly harmless): can wrap around if file > 4gb */ | 315 | G.curFileSize = statf.st_size; |
346 | G.curFileSize = statf.st_size; | ||
347 | } | 316 | } |
348 | #endif | 317 | #endif |
349 | } | 318 | } |