Browse code

New FIFO using fifo_reply and fixing previous shortcomings in blocking thru unsucessful randez-vous mit FIFO client

Jiri Kuthan authored on 03/09/2002 08:38:00
Showing 5 changed files
... ...
@@ -112,4 +112,10 @@
112 112
 */
113 113
 #define CLEANUP_EOL "      \n"
114 114
 
115
+/* how patient is ser with FIFO clients not awaiting a reply? 
116
+	4 x 80ms = 0.32 sec
117
+*/
118
+#define FIFO_REPLY_RETRIES	4
119
+#define FIFO_REPLY_WAIT		80000
120
+
115 121
 #endif
... ...
@@ -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 */