comparison libfdcore/hooks.c @ 1215:65c6460f60f2

Ensure the hooks lock is released when a thread is canceled. Optimize the default hook behavior to avoid too many mallocs/free
author Sebastien Decugis <sdecugis@freediameter.net>
date Wed, 19 Jun 2013 10:20:47 +0800
parents 40330b75c044
children 4b511d9b3def
comparison
equal deleted inserted replaced
1214:c2fbaf2985f4 1215:65c6460f60f2
278 va_end(ap); 278 va_end(ap);
279 279
280 return ret; 280 return ret;
281 } 281 }
282 282
283 static pthread_mutex_t hook_default_mtx = PTHREAD_MUTEX_INITIALIZER;
284 static char * hook_default_buf = NULL;
285 static size_t hook_default_len = 0;
286
283 /* The function that does the work of calling the extension's callbacks and also managing the permessagedata structures */ 287 /* The function that does the work of calling the extension's callbacks and also managing the permessagedata structures */
284 void fd_hook_call(enum fd_hook_type type, struct msg * msg, struct fd_peer * peer, void * other, struct fd_msg_pmdl * pmdl) 288 void fd_hook_call(enum fd_hook_type type, struct msg * msg, struct fd_peer * peer, void * other, struct fd_msg_pmdl * pmdl)
285 { 289 {
286 struct fd_list * li; 290 struct fd_list * li;
287 ASSERT(type <= HOOK_LAST); 291 ASSERT(type <= HOOK_LAST);
288 int call_default = 0; 292 int call_default = 0;
289 293
290 /* lock the list of hooks for this type */ 294 /* lock the list of hooks for this type */
291 CHECK_POSIX_DO( pthread_rwlock_rdlock(&HS_array[type].rwlock), ); 295 CHECK_POSIX_DO( pthread_rwlock_rdlock(&HS_array[type].rwlock), );
296
297 pthread_cleanup_push( fd_cleanup_rwlock, &HS_array[type].rwlock );
292 298
293 if (FD_IS_LIST_EMPTY(&HS_array[type].sentinel)) { 299 if (FD_IS_LIST_EMPTY(&HS_array[type].sentinel)) {
294 call_default = 1; 300 call_default = 1;
295 } else { 301 } else {
296 /* for each registered hook */ 302 /* for each registered hook */
306 /* Now, call this callback */ 312 /* Now, call this callback */
307 (*h->fd_hook_cb)(type, msg, &peer->p_hdr, other, pmd, h->regdata); 313 (*h->fd_hook_cb)(type, msg, &peer->p_hdr, other, pmd, h->regdata);
308 } 314 }
309 } 315 }
310 316
317 pthread_cleanup_pop(0);
318
311 /* done */ 319 /* done */
312 CHECK_POSIX_DO( pthread_rwlock_unlock(&HS_array[type].rwlock), ); 320 CHECK_POSIX_DO( pthread_rwlock_unlock(&HS_array[type].rwlock), );
313 321
314 if (call_default) { 322 if (call_default) {
315 char * buf = NULL; 323 CHECK_POSIX_DO( pthread_mutex_lock(&hook_default_mtx), );
316 size_t len = 0; 324
325 pthread_cleanup_push( fd_cleanup_mutex, &hook_default_mtx );
317 326
318 /* There was no registered handler, default behavior for this hook */ 327 /* There was no registered handler, default behavior for this hook */
319 switch (type) { 328 switch (type) {
320 case HOOK_DATA_RECEIVED: { 329 case HOOK_DATA_RECEIVED: {
321 struct fd_cnx_rcvdata *rcv_data = other; 330 struct fd_cnx_rcvdata *rcv_data = other;
322 LOG_A("RCV: %zd bytes", rcv_data->length); 331 LOG_A("RCV: %zd bytes", rcv_data->length);
323 break; 332 break;
324 } 333 }
325 334
326 case HOOK_MESSAGE_RECEIVED: { 335 case HOOK_MESSAGE_RECEIVED: {
327 CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); 336 CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
328 LOG_D("RCV from '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); 337 LOG_D("RCV from '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf);
329 break; 338 break;
330 } 339 }
331 340
332 case HOOK_MESSAGE_LOCAL: { 341 case HOOK_MESSAGE_LOCAL: {
333 CHECK_MALLOC_DO(fd_msg_dump_full(&buf, &len, NULL, msg, NULL, 0, 1), break); 342 CHECK_MALLOC_DO(fd_msg_dump_full(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
334 LOG_A("Handled to framework for sending: %s", buf); 343 LOG_A("Handled to framework for sending: %s", hook_default_buf);
335 break; 344 break;
336 } 345 }
337 346
338 case HOOK_MESSAGE_SENT: { 347 case HOOK_MESSAGE_SENT: {
339 CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); 348 CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
340 LOG_D("SENT to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); 349 LOG_D("SENT to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf);
341 break; 350 break;
342 } 351 }
343 352
344 case HOOK_MESSAGE_FAILOVER: { 353 case HOOK_MESSAGE_FAILOVER: {
345 CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); 354 CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
346 LOG_D("Failing over message sent to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); 355 LOG_D("Failing over message sent to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf);
347 break; 356 break;
348 } 357 }
349 358
350 case HOOK_MESSAGE_PARSING_ERROR: { 359 case HOOK_MESSAGE_PARSING_ERROR: {
351 if (msg) { 360 if (msg) {
354 id = (DiamId_t)"<error getting source>"; 363 id = (DiamId_t)"<error getting source>";
355 364
356 if (!id) 365 if (!id)
357 id = (DiamId_t)"<local>"; 366 id = (DiamId_t)"<local>";
358 367
359 CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); 368 CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
360 369
361 LOG_E("Parsing error: '%s' for the following message received from '%s':", (char *)other, (char *)id); 370 LOG_E("Parsing error: '%s' for the following message received from '%s':", (char *)other, (char *)id);
362 LOG_SPLIT(FD_LOG_ERROR, " ", buf?:"<error dumping message>", NULL); 371 LOG_SPLIT(FD_LOG_ERROR, " ", hook_default_buf, NULL);
363 } else { 372 } else {
364 struct fd_cnx_rcvdata *rcv_data = other; 373 struct fd_cnx_rcvdata *rcv_data = other;
365 CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break); 374 CHECK_MALLOC_DO(fd_dump_extend_hexdump(&hook_default_buf, &hook_default_len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break);
366 LOG_E("Parsing error: cannot parse %zdB buffer from '%s': %s", rcv_data->length, peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); 375 LOG_E("Parsing error: cannot parse %zdB buffer from '%s': %s", rcv_data->length, peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf);
367 } 376 }
368 break; 377 break;
369 } 378 }
370 379
371 case HOOK_MESSAGE_ROUTING_ERROR: { 380 case HOOK_MESSAGE_ROUTING_ERROR: {
372 CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); 381 CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
373 LOG_E("Routing error: '%s' for the following message:", (char *)other); 382 LOG_E("Routing error: '%s' for the following message:", (char *)other);
374 LOG_SPLIT(FD_LOG_ERROR, " ", buf?:"<error dumping message>", NULL); 383 LOG_SPLIT(FD_LOG_ERROR, " ", hook_default_buf, NULL);
375 break; 384 break;
376 } 385 }
377 386
378 case HOOK_MESSAGE_ROUTING_FORWARD: { 387 case HOOK_MESSAGE_ROUTING_FORWARD: {
379 CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); 388 CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
380 LOG_D("FORWARDING: %s", buf); 389 LOG_D("FORWARDING: %s", hook_default_buf);
381 break; 390 break;
382 } 391 }
383 392
384 case HOOK_MESSAGE_ROUTING_LOCAL: { 393 case HOOK_MESSAGE_ROUTING_LOCAL: {
385 CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); 394 CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
386 LOG_D("DISPATCHING: %s", buf); 395 LOG_D("DISPATCHING: %s", hook_default_buf);
387 break; 396 break;
388 } 397 }
389 398
390 case HOOK_MESSAGE_DROPPED: { 399 case HOOK_MESSAGE_DROPPED: {
391 CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); 400 CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
392 LOG_E("Message discarded ('%s'):", (char *)other); 401 LOG_E("Message discarded ('%s'):", (char *)other);
393 LOG_SPLIT(FD_LOG_ERROR, " ", buf?:"<error dumping message>", NULL); 402 LOG_SPLIT(FD_LOG_ERROR, " ", hook_default_buf, NULL);
394 break; 403 break;
395 } 404 }
396 405
397 case HOOK_PEER_CONNECT_FAILED: { 406 case HOOK_PEER_CONNECT_FAILED: {
398 if (msg) { 407 if (msg) {
399 CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); 408 CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
400 LOG_N("Connection to '%s' failed: '%s'; CER/CEA dump:", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other); 409 LOG_N("Connection to '%s' failed: '%s'; CER/CEA dump:", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other);
401 LOG_SPLIT(FD_LOG_NOTICE, " ", buf?:"<error dumping message>", NULL); 410 LOG_SPLIT(FD_LOG_NOTICE, " ", hook_default_buf, NULL);
402 } else { 411 } else {
403 LOG_D("Connection to '%s' failed: %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other); 412 LOG_D("Connection to '%s' failed: %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other);
404 } 413 }
405 break; 414 break;
406 } 415 }
408 case HOOK_PEER_CONNECT_SUCCESS: { 417 case HOOK_PEER_CONNECT_SUCCESS: {
409 DiamId_t id = NULL; 418 DiamId_t id = NULL;
410 if ((!fd_msg_source_get( msg, &id, NULL )) && (id == NULL)) { /* The CEA is locally issued */ 419 if ((!fd_msg_source_get( msg, &id, NULL )) && (id == NULL)) { /* The CEA is locally issued */
411 fd_msg_answ_getq(msg, &msg); /* We dump the CER in that case */ 420 fd_msg_answ_getq(msg, &msg); /* We dump the CER in that case */
412 } 421 }
413 CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); 422 CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break);
414 char protobuf[40]; 423 char protobuf[40];
415 if (peer) { 424 if (peer) {
416 CHECK_FCT_DO(fd_peer_cnx_proto_info(&peer->p_hdr, protobuf, sizeof(protobuf)), break ); 425 CHECK_FCT_DO(fd_peer_cnx_proto_info(&peer->p_hdr, protobuf, sizeof(protobuf)), break );
417 } else { 426 } else {
418 protobuf[0] = '-'; 427 protobuf[0] = '-';
419 protobuf[1] = '\0'; 428 protobuf[1] = '\0';
420 } 429 }
421 LOG_N("Connected to '%s' (%s), remote capabilities: ", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", protobuf); 430 LOG_N("Connected to '%s' (%s), remote capabilities: ", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", protobuf);
422 LOG_SPLIT(FD_LOG_NOTICE, " ", buf?:"<error dumping message>", NULL); 431 LOG_SPLIT(FD_LOG_NOTICE, " ", hook_default_buf, NULL);
423 break; 432 break;
424 } 433 }
425 434
426 } 435 }
427 436
428 free(buf); 437 pthread_cleanup_pop(0);
429 } 438
430 } 439 CHECK_POSIX_DO( pthread_mutex_unlock(&hook_default_mtx), );
440 }
441 }
"Welcome to our mercurial repository"