... | ... |
@@ -39,6 +39,7 @@ |
39 | 39 |
#include <signal.h> |
40 | 40 |
#include <string.h> |
41 | 41 |
#include <time.h> |
42 |
+#include <stdarg.h> |
|
42 | 43 |
#include "dprint.h" |
43 | 44 |
#include "ut.h" |
44 | 45 |
#include "error.h" |
... | ... |
@@ -256,9 +257,11 @@ static char *trim_filename( char * file ) |
256 | 257 |
} |
257 | 258 |
|
258 | 259 |
/* tell FIFO client what happened via reply pipe */ |
259 |
-void fifo_reply( char *reply_fifo, char *reply_txt) |
|
260 |
+void fifo_reply( char *reply_fifo, char *reply_fmt, ... ) |
|
260 | 261 |
{ |
261 | 262 |
FILE *file_handle; |
263 |
+ int r; |
|
264 |
+ va_list ap; |
|
262 | 265 |
|
263 | 266 |
file_handle=open_reply_pipe(reply_fifo); |
264 | 267 |
if (file_handle==0) { |
... | ... |
@@ -266,22 +269,59 @@ void fifo_reply( char *reply_fifo, char *reply_txt) |
266 | 269 |
fifo); |
267 | 270 |
return; |
268 | 271 |
} |
269 |
- if (fprintf(file_handle, "%s", reply_txt)<=0) { |
|
272 |
+retry: |
|
273 |
+ va_start(ap, reply_fmt); |
|
274 |
+ r=vfprintf(file_handle, reply_fmt, ap); |
|
275 |
+ va_end(ap); |
|
276 |
+ if (r<=0) { |
|
270 | 277 |
LOG(L_ERR, "ERROR: fifo_error: write error (%s): %s\n", |
271 | 278 |
fifo, strerror(errno)); |
279 |
+ if ((errno==EINTR)||(errno==EAGAIN)||(errno==EWOULDBLOCK)) { |
|
280 |
+ goto retry; |
|
281 |
+ } |
|
272 | 282 |
} |
273 | 283 |
fclose(file_handle); |
274 | 284 |
} |
275 | 285 |
|
276 | 286 |
FILE *open_reply_pipe( char *pipe_name ) |
277 | 287 |
{ |
288 |
+ |
|
289 |
+ int fifofd; |
|
278 | 290 |
FILE *file_handle; |
279 | 291 |
|
280 |
- if (!pipe_name) { |
|
292 |
+ int retries=FIFO_REPLY_RETRIES; |
|
293 |
+ |
|
294 |
+ if (!pipe_name || *pipe_name==0) { |
|
281 | 295 |
DBG("DEBUG: open_reply_pipe: no file to write to about missing cmd\n"); |
282 | 296 |
return 0; |
283 | 297 |
} |
284 |
- file_handle=fopen( pipe_name, "w"); |
|
298 |
+ |
|
299 |
+tryagain: |
|
300 |
+ fifofd=open( pipe_name, O_WRONLY | O_NONBLOCK ); |
|
301 |
+ if (fifofd==-1) { |
|
302 |
+ /* retry several times if client is not yet ready for getting |
|
303 |
+ feedback via a reply pipe |
|
304 |
+ */ |
|
305 |
+ if (errno==ENXIO) { |
|
306 |
+ /* give up on the client - we can't afford server blocking */ |
|
307 |
+ if (retries==0) { |
|
308 |
+ LOG(L_ERR, "ERROR: open_reply_pipe: no client at %s\n", |
|
309 |
+ pipe_name ); |
|
310 |
+ return 0; |
|
311 |
+ } |
|
312 |
+ /* don't be noisy on the very first try */ |
|
313 |
+ if (retries!=FIFO_REPLY_RETRIES) |
|
314 |
+ DBG("DEBUG: open_reply_pipe: retry countdown: %d\n", retries ); |
|
315 |
+ sleep_us( FIFO_REPLY_WAIT ); |
|
316 |
+ retries--; |
|
317 |
+ goto tryagain; |
|
318 |
+ } |
|
319 |
+ /* some other opening error */ |
|
320 |
+ LOG(L_ERR, "ERROR: open_reply_pipe: open error (%s): %s\n", |
|
321 |
+ pipe_name, strerror(errno)); |
|
322 |
+ return 0; |
|
323 |
+ } |
|
324 |
+ file_handle=fdopen( fifofd, "w"); |
|
285 | 325 |
if (file_handle==NULL) { |
286 | 326 |
LOG(L_ERR, "ERROR: open_reply_pipe: open error (%s): %s\n", |
287 | 327 |
pipe_name, strerror(errno)); |
... | ... |
@@ -296,7 +336,6 @@ static void fifo_server(FILE *fifo_stream) |
296 | 336 |
int line_len; |
297 | 337 |
char *file_sep, *command, *file; |
298 | 338 |
struct fifo_command *f; |
299 |
- FILE *file_handle; |
|
300 | 339 |
|
301 | 340 |
file_sep=command=file=0; |
302 | 341 |
|
... | ... |
@@ -349,33 +388,12 @@ static void fifo_server(FILE *fifo_stream) |
349 | 388 |
if (f==0) { |
350 | 389 |
LOG(L_ERR, "ERROR: fifo_server: command %s is not available\n", |
351 | 390 |
command); |
352 |
- file_handle=open_reply_pipe(file); |
|
353 |
- if (file_handle==0) { |
|
354 |
- LOG(L_ERR, "ERROR: fifo_server: no reply pipe\n"); |
|
355 |
- goto consume; |
|
356 |
- } |
|
357 |
- if (fprintf(file_handle, "[%s not available]\n", command)<=0) { |
|
358 |
- LOG(L_ERR, "ERROR: fifo_server: write error: %s\n", |
|
359 |
- strerror(errno)); |
|
360 |
- } |
|
361 |
- fclose(file_handle); |
|
391 |
+ fifo_reply(file, "[%s not available]\n", command); |
|
362 | 392 |
goto consume; |
363 | 393 |
} |
364 | 394 |
if (f->f(fifo_stream, file)<0) { |
365 | 395 |
LOG(L_ERR, "ERROR: fifo_server: command (%s) " |
366 | 396 |
"processing failed\n", command ); |
367 |
-#ifdef _OBSOLETED |
|
368 |
- file_handle=open_reply_pipe(file); |
|
369 |
- if (file_handle==0) { |
|
370 |
- LOG(L_ERR, "ERROR: fifo_server: no reply pipe\n"); |
|
371 |
- goto consume; |
|
372 |
- } |
|
373 |
- if (fprintf(file_handle, "[%s failed]\n", command)<=0) { |
|
374 |
- LOG(L_ERR, "ERROR: fifo_server: write error: %s\n", |
|
375 |
- strerror(errno)); |
|
376 |
- } |
|
377 |
- fclose(file_handle); |
|
378 |
-#endif |
|
379 | 397 |
goto consume; |
380 | 398 |
} |
381 | 399 |
|
... | ... |
@@ -433,6 +451,8 @@ int open_fifo_server() |
433 | 451 |
strerror(errno)); |
434 | 452 |
return -1; |
435 | 453 |
} |
454 |
+ /* a real server doesn't die if writing to reply fifo fails */ |
|
455 |
+ signal(SIGPIPE, SIG_IGN); |
|
436 | 456 |
LOG(L_INFO, "SER: open_uac_fifo: fifo server up at %s...\n", |
437 | 457 |
fifo); |
438 | 458 |
fifo_server( fifo_stream ); /* never retruns */ |
... | ... |
@@ -453,21 +473,6 @@ static int print_version_cmd( FILE *stream, char *response_file ) |
453 | 473 |
{ |
454 | 474 |
if (response_file) { |
455 | 475 |
fifo_reply(response_file, SERVER_HDR CRLF ); |
456 |
-#ifdef _OBSOLETED |
|
457 |
- file=open( response_file, O_WRONLY ); |
|
458 |
- if (file<0) { |
|
459 |
- LOG(L_ERR, "ERROR: print_version_cmd: open error (%s): %s\n", |
|
460 |
- response_file, strerror(errno)); |
|
461 |
- return -1; |
|
462 |
- } |
|
463 |
- if (write(file, SERVER_HDR CRLF, SERVER_HDR_LEN+CRLF_LEN)<0) { |
|
464 |
- LOG(L_ERR, "ERROR: print_version_cmd: write error: %s\n", |
|
465 |
- strerror(errno)); |
|
466 |
- close(file); |
|
467 |
- return -1; |
|
468 |
- } |
|
469 |
- close(file); |
|
470 |
-#endif |
|
471 | 476 |
} else { |
472 | 477 |
LOG(L_ERR, "ERROR: no file for print_version_cmd\n"); |
473 | 478 |
} |
... | ... |
@@ -487,9 +492,6 @@ static int print_fifo_cmd( FILE *stream, char *response_file ) |
487 | 492 |
return -1; |
488 | 493 |
} |
489 | 494 |
if (!read_line(text, MAX_PRINT_TEXT, stream, &text_len)) { |
490 |
-#ifdef _OBSOLETED |
|
491 |
- LOG(L_ERR, "ERROR: print_fifo_cmd: too big text\n"); |
|
492 |
-#endif |
|
493 | 495 |
fifo_reply(response_file, |
494 | 496 |
"ERROR: print_fifo_cmd: too big text"); |
495 | 497 |
return -1; |
... | ... |
@@ -497,21 +499,6 @@ static int print_fifo_cmd( FILE *stream, char *response_file ) |
497 | 499 |
/* now the work begins */ |
498 | 500 |
if (response_file) { |
499 | 501 |
fifo_reply(response_file, text ); |
500 |
-#ifdef _OBSOLETED |
|
501 |
- file=open( response_file , O_WRONLY); |
|
502 |
- if (file<0) { |
|
503 |
- LOG(L_ERR, "ERROR: print_fifo_cmd: open error (%s): %s\n", |
|
504 |
- response_file, strerror(errno)); |
|
505 |
- return -1; |
|
506 |
- } |
|
507 |
- if (write(file, text,text_len)<0) { |
|
508 |
- LOG(L_ERR, "ERROR: print_fifo_cmd: write error: %s\n", |
|
509 |
- strerror(errno)); |
|
510 |
- close(file); |
|
511 |
- return 1; |
|
512 |
- } |
|
513 |
- close(file); |
|
514 |
-#endif |
|
515 | 502 |
} else { |
516 | 503 |
LOG(L_INFO, "INFO: print_fifo_cmd: %.*s\n", |
517 | 504 |
text_len, text ); |
... | ... |
@@ -521,14 +508,20 @@ static int print_fifo_cmd( FILE *stream, char *response_file ) |
521 | 508 |
|
522 | 509 |
static int uptime_fifo_cmd( FILE *stream, char *response_file ) |
523 | 510 |
{ |
524 |
- FILE *file; |
|
525 | 511 |
time_t now; |
526 | 512 |
|
527 | 513 |
if (response_file==0 || *response_file==0 ) { |
528 | 514 |
LOG(L_ERR, "ERROR: uptime_fifo_cmd: null file\n"); |
529 | 515 |
return -1; |
530 | 516 |
} |
531 |
- file=fopen(response_file, "w" ); |
|
517 |
+ |
|
518 |
+ time(&now); |
|
519 |
+ fifo_reply( response_file, "Now: %sUp Since: %sUp time: %.0f [sec]\n", |
|
520 |
+ ctime(&now), ctime(&up_since), difftime(now, up_since) ); |
|
521 |
+ |
|
522 |
+#ifdef _OBSOLETED |
|
523 |
+ |
|
524 |
+ file=open_reply_pipe(response_file); |
|
532 | 525 |
if (file==NULL) { |
533 | 526 |
LOG(L_ERR, "ERROR: uptime_fifo_cmd: file %s bad: %s\n", |
534 | 527 |
response_file, strerror(errno) ); |
... | ... |
@@ -536,11 +529,31 @@ static int uptime_fifo_cmd( FILE *stream, char *response_file ) |
536 | 529 |
} |
537 | 530 |
|
538 | 531 |
time(&now); |
539 |
- fprintf(file, "Now: %s", ctime(&now) ); |
|
540 |
- fprintf(file, "Up since: %s", ctime(&up_since) ); |
|
541 |
- fprintf(file, "Up time: %.0f [sec]\n", difftime(now, up_since)); |
|
532 |
+ |
|
533 |
+ r=fprintf(file, "Now: %s", ctime(&now) ); |
|
534 |
+ r=1; |
|
535 |
+ if (r<=0) { |
|
536 |
+ printf("XXX: r: %d : %s\n", r, strerror(errno)); |
|
537 |
+ goto done; |
|
538 |
+ } |
|
539 |
+ |
|
540 |
+ r=fprintf(file, "Up since: %s", ctime(&up_since) ); |
|
541 |
+ r=1; |
|
542 |
+ if (r<=0) { |
|
543 |
+ printf("XXX: r: %d : %s\n", r, strerror(errno)); |
|
544 |
+ goto done; |
|
545 |
+ } |
|
546 |
+ r=fprintf(file, "Up time: %.0f [sec]\n", difftime(now, up_since)); |
|
547 |
+ r=1; |
|
548 |
+ if (r<=0) { |
|
549 |
+ printf("XXX: r: %d : %s\n", r, strerror(errno)); |
|
550 |
+ goto done; |
|
551 |
+ } |
|
552 |
+ |
|
553 |
+done: |
|
542 | 554 |
|
543 | 555 |
fclose(file); |
556 |
+#endif |
|
544 | 557 |
return 1; |
545 | 558 |
} |
546 | 559 |
|
... | ... |
@@ -43,7 +43,7 @@ int register_core_fifo(); |
43 | 43 |
FILE *open_reply_pipe( char *pipe_name ); |
44 | 44 |
|
45 | 45 |
/* tell FIFO client an error occured via reply pipe */ |
46 |
-void fifo_reply( char *reply_fifo, char *reply_txt); |
|
46 |
+void fifo_reply( char *reply_fifo, char *reply_fmt, ... ); |
|
47 | 47 |
|
48 | 48 |
|
49 | 49 |
#endif |
... | ... |
@@ -61,7 +61,7 @@ int static fifo_stats( FILE *pipe, char *response_file ) |
61 | 61 |
return -1; |
62 | 62 |
} |
63 | 63 |
|
64 |
- file=fopen(response_file, "w" ); |
|
64 |
+ file=open_reply_pipe(response_file ); |
|
65 | 65 |
if (file==NULL) { |
66 | 66 |
LOG(L_ERR, "ERROR: fifo_stats: file %s bad: %s\n", |
67 | 67 |
response_file, strerror(errno) ); |
... | ... |
@@ -211,35 +211,24 @@ static void fifo_callback( struct cell *t, struct sip_msg *msg, |
211 | 211 |
{ |
212 | 212 |
|
213 | 213 |
char *filename; |
214 |
- int file; |
|
215 |
- int r; |
|
216 | 214 |
str text; |
217 | 215 |
|
218 | 216 |
DBG("DEBUG: fifo UAC completed with status %d\n", code); |
219 |
- if (t->cbp) { |
|
220 |
- filename=(char *)(t->cbp); |
|
221 |
- file=open(filename, O_WRONLY); |
|
222 |
- if (file<0) { |
|
223 |
- LOG(L_ERR, "ERROR: fifo_callback: can't open file %s: %s\n", |
|
224 |
- filename, strerror(errno)); |
|
225 |
- return; |
|
226 |
- } |
|
227 |
- get_reply_status(&text,msg,code); |
|
228 |
- if (text.s==0) { |
|
229 |
- LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n"); |
|
230 |
- return; |
|
231 |
- } |
|
232 |
- r=write(file, text.s , text.len ); |
|
233 |
- close(file); |
|
234 |
- pkg_free(text.s); |
|
235 |
- if (r<0) { |
|
236 |
- LOG(L_ERR, "ERROR: fifo_callback: write error: %s\n", |
|
237 |
- strerror(errno)); |
|
238 |
- return; |
|
239 |
- } |
|
240 |
- } else { |
|
217 |
+ if (!t->cbp) { |
|
241 | 218 |
LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", code); |
219 |
+ return; |
|
220 |
+ } |
|
221 |
+ |
|
222 |
+ filename=(char *)(t->cbp); |
|
223 |
+ get_reply_status(&text,msg,code); |
|
224 |
+ if (text.s==0) { |
|
225 |
+ LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n"); |
|
226 |
+ fifo_reply(filename, "ERROR: fifo_callback: get_reply_status failed\n"); |
|
227 |
+ return; |
|
242 | 228 |
} |
229 |
+ fifo_reply(filename, "%.*s", text.len, text.s ); |
|
230 |
+ pkg_free(text.s); |
|
231 |
+ DBG("DEBUG: fifo_callback sucesssfuly completed\n"); |
|
243 | 232 |
} |
244 | 233 |
|
245 | 234 |
/* to be obsoleted in favor of fifo_uac_from */ |