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 256
 }
257 257
 
258 258
 /* tell FIFO client what happened via reply pipe */
259
-void fifo_reply( char *reply_fifo, char *reply_txt)
259
+void fifo_reply( char *reply_fifo, char *reply_fmt, ... )
260 260
 {
261 261
 	FILE *file_handle;
262
+	int r;
263
+	va_list ap;
262 264
 
263 265
 	file_handle=open_reply_pipe(reply_fifo);
264 266
 	if (file_handle==0) {
... ...
@@ -266,22 +269,59 @@ void fifo_reply( char *reply_fifo, char *reply_txt)
266 266
 			fifo);
267 267
 		return;
268 268
 	}
269
-	if (fprintf(file_handle, "%s", reply_txt)<=0) {
269
+retry:
270
+	va_start(ap, reply_fmt);
271
+	r=vfprintf(file_handle, reply_fmt, ap);
272
+	va_end(ap);
273
+	if (r<=0) {
270 274
 		LOG(L_ERR, "ERROR: fifo_error: write error (%s): %s\n",
271 275
 			fifo, strerror(errno));
276
+		if ((errno==EINTR)||(errno==EAGAIN)||(errno==EWOULDBLOCK)) {
277
+			goto retry;
278
+		}
272 279
 	}
273 280
 	fclose(file_handle);
274 281
 }
275 282
 
276 283
 FILE *open_reply_pipe( char *pipe_name )
277 284
 {
285
+
286
+	int fifofd;
278 287
 	FILE *file_handle;
279 288
 
280
-	if (!pipe_name) {
289
+	int retries=FIFO_REPLY_RETRIES;
290
+
291
+	if (!pipe_name || *pipe_name==0) {
281 292
 		DBG("DEBUG: open_reply_pipe: no file to write to about missing cmd\n");
282 293
 		return 0;
283 294
 	}
284
-	file_handle=fopen( pipe_name, "w");
295
+
296
+tryagain:
297
+	fifofd=open( pipe_name, O_WRONLY | O_NONBLOCK );
298
+	if (fifofd==-1) {
299
+		/* retry several times if client is not yet ready for getting
300
+		   feedback via a reply pipe
301
+		*/
302
+		if (errno==ENXIO) {
303
+			/* give up on the client - we can't afford server blocking */
304
+			if (retries==0) {
305
+				LOG(L_ERR, "ERROR: open_reply_pipe: no client at %s\n",
306
+					pipe_name );
307
+				return 0;
308
+			}
309
+			/* don't be noisy on the very first try */
310
+			if (retries!=FIFO_REPLY_RETRIES)
311
+				DBG("DEBUG: open_reply_pipe: retry countdown: %d\n", retries );
312
+			sleep_us( FIFO_REPLY_WAIT );
313
+			retries--;
314
+			goto tryagain;
315
+		}
316
+		/* some other opening error */
317
+		LOG(L_ERR, "ERROR: open_reply_pipe: open error (%s): %s\n",
318
+			pipe_name, strerror(errno));
319
+		return 0;
320
+	}
321
+	file_handle=fdopen( fifofd, "w");
285 322
 	if (file_handle==NULL) {
286 323
 		LOG(L_ERR, "ERROR: open_reply_pipe: open error (%s): %s\n",
287 324
 			pipe_name, strerror(errno));
... ...
@@ -296,7 +336,6 @@ static void fifo_server(FILE *fifo_stream)
296 296
 	int line_len;
297 297
 	char *file_sep, *command, *file;
298 298
 	struct fifo_command *f;
299
-	FILE *file_handle;
300 299
 
301 300
 	file_sep=command=file=0;
302 301
 
... ...
@@ -349,33 +388,12 @@ static void fifo_server(FILE *fifo_stream)
349 349
 		if (f==0) {
350 350
 			LOG(L_ERR, "ERROR: fifo_server: command %s is not available\n",
351 351
 				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);
352
+			fifo_reply(file, "[%s not available]\n", command);
362 353
 			goto consume;
363 354
 		}
364 355
 		if (f->f(fifo_stream, file)<0) {
365 356
 			LOG(L_ERR, "ERROR: fifo_server: command (%s) "
366 357
 				"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 358
 			goto consume;
380 359
 		}
381 360
 
... ...
@@ -433,6 +451,8 @@ int open_fifo_server()
433 433
 				strerror(errno));
434 434
 			return -1;
435 435
 		}
436
+		/* a real server doesn't die if writing to reply fifo fails */
437
+		signal(SIGPIPE, SIG_IGN);
436 438
 		LOG(L_INFO, "SER: open_uac_fifo: fifo server up at %s...\n",
437 439
 			fifo);
438 440
 		fifo_server( fifo_stream ); /* never retruns */
... ...
@@ -453,21 +473,6 @@ static int print_version_cmd( FILE *stream, char *response_file )
453 453
 {
454 454
 	if (response_file) {
455 455
 		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 456
 	} else {
472 457
 		LOG(L_ERR, "ERROR: no file for print_version_cmd\n");
473 458
 	}
... ...
@@ -487,9 +492,6 @@ static int print_fifo_cmd( FILE *stream, char *response_file )
487 487
 		return -1;
488 488
 	}
489 489
 	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 490
 		fifo_reply(response_file, 
494 491
 			"ERROR: print_fifo_cmd: too big text");
495 492
 		return -1;
... ...
@@ -497,21 +499,6 @@ static int print_fifo_cmd( FILE *stream, char *response_file )
497 497
 	/* now the work begins */
498 498
 	if (response_file) {
499 499
 		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 500
 	} else {
516 501
 		LOG(L_INFO, "INFO: print_fifo_cmd: %.*s\n", 
517 502
 			text_len, text );
... ...
@@ -521,14 +508,20 @@ static int print_fifo_cmd( FILE *stream, char *response_file )
521 521
 
522 522
 static int uptime_fifo_cmd( FILE *stream, char *response_file )
523 523
 {
524
-	FILE *file;
525 524
 	time_t now;
526 525
 
527 526
 	if (response_file==0 || *response_file==0 ) { 
528 527
 		LOG(L_ERR, "ERROR: uptime_fifo_cmd: null file\n");
529 528
 		return -1;
530 529
 	}
531
-	file=fopen(response_file, "w" );
530
+
531
+	time(&now);
532
+	fifo_reply( response_file, "Now: %sUp Since: %sUp time: %.0f [sec]\n",
533
+		ctime(&now), ctime(&up_since), difftime(now, up_since) );
534
+
535
+#ifdef _OBSOLETED
536
+
537
+	file=open_reply_pipe(response_file);
532 538
 	if (file==NULL) {
533 539
 		LOG(L_ERR, "ERROR: uptime_fifo_cmd: file %s bad: %s\n",
534 540
 			response_file, strerror(errno) );
... ...
@@ -536,11 +529,31 @@ static int uptime_fifo_cmd( FILE *stream, char *response_file )
536 536
 	}
537 537
 
538 538
 	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));
539
+
540
+	r=fprintf(file, "Now: %s", ctime(&now) );
541
+	r=1;
542
+	if (r<=0) {
543
+		printf("XXX: r: %d : %s\n", r, strerror(errno));
544
+		goto done;
545
+	}
546
+
547
+	r=fprintf(file, "Up since: %s", ctime(&up_since) );
548
+	r=1;
549
+	if (r<=0) {
550
+		printf("XXX: r: %d : %s\n", r, strerror(errno));
551
+		goto done;
552
+	}
553
+	r=fprintf(file, "Up time: %.0f [sec]\n", difftime(now, up_since));
554
+	r=1;
555
+	if (r<=0) {
556
+		printf("XXX: r: %d : %s\n", r, strerror(errno));
557
+		goto done;
558
+	}
559
+
560
+done:
542 561
 
543 562
 	fclose(file);
563
+#endif
544 564
 	return 1;
545 565
 }
546 566
 
... ...
@@ -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 */