jcs's openbsd hax
openbsd

Move libagentx to a new freeing strategy, where we check all objects when a close packet has been received.

This should have little to no performance impact in practice, since under
normal operations we shouldn't free any objects.

OK bluhm@

martijn f00a771d 8b1f2e0e

+188 -168
+186 -167
lib/libagentx/agentx.c
··· 1 - /* $OpenBSD: agentx.c,v 1.10 2021/06/02 08:40:09 martijn Exp $ */ 1 + /* $OpenBSD: agentx.c,v 1.11 2021/10/23 14:39:35 martijn Exp $ */ 2 2 /* 3 3 * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org> 4 4 * ··· 270 270 struct agentx_session *axs, *tsas; 271 271 struct agentx_request *axr; 272 272 struct agentx_get *axg; 273 + int axfree = ax->ax_free; 273 274 274 275 ax_free(ax->ax_ax); 275 276 ax->ax_ax = NULL; 276 277 ax->ax_fd = -1; 278 + ax->ax_free = 1; 277 279 278 280 ax->ax_cstate = AX_CSTATE_CLOSE; 279 281 ··· 289 291 TAILQ_REMOVE(&(ax->ax_getreqs), axg, axg_ax_getreqs); 290 292 } 291 293 292 - if (ax->ax_dstate == AX_DSTATE_CLOSE) { 294 + if (ax->ax_dstate == AX_DSTATE_OPEN) 295 + agentx_start(ax); 296 + 297 + if (!axfree) 293 298 agentx_free_finalize(ax); 294 - return; 295 - } 296 - 297 - agentx_start(ax); 298 299 } 299 300 300 301 void 301 302 agentx_free(struct agentx *ax) 302 303 { 303 304 struct agentx_session *axs, *tsas; 305 + int axfree; 304 306 305 307 if (ax == NULL) 306 308 return; 307 309 308 - if (ax->ax_dstate == AX_DSTATE_CLOSE) { 309 - /* Malloc throws abort on invalid pointers as well */ 310 + axfree = ax->ax_free; 311 + ax->ax_free = 1; 312 + 313 + /* Malloc throws abort on invalid pointers as well */ 314 + if (ax->ax_dstate == AX_DSTATE_CLOSE) 310 315 agentx_log_ax_fatalx(ax, "%s: double free", __func__); 311 - } 312 316 ax->ax_dstate = AX_DSTATE_CLOSE; 313 317 314 - if (!TAILQ_EMPTY(&(ax->ax_sessions))) { 315 - TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions, 316 - tsas) { 317 - if (axs->axs_dstate != AX_DSTATE_CLOSE) 318 - agentx_session_free(axs); 319 - } 320 - } else 318 + TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions, tsas) { 319 + if (axs->axs_dstate != AX_DSTATE_CLOSE) 320 + agentx_session_free(axs); 321 + } 322 + if (!axfree) 321 323 agentx_free_finalize(ax); 322 324 } 323 325 324 326 static void 325 327 agentx_free_finalize(struct agentx *ax) 326 328 { 327 - #ifdef AX_DEBUG 328 - if (ax->ax_dstate != AX_DSTATE_CLOSE) 329 - agentx_log_ax_fatalx(ax, "%s: agentx not closing", 330 - __func__); 331 - if (!TAILQ_EMPTY(&(ax->ax_sessions))) 332 - agentx_log_ax_fatalx(ax, "%s: agentx still has sessions", 333 - __func__); 334 - if (!RB_EMPTY(&(ax->ax_requests))) 335 - agentx_log_ax_fatalx(ax, 336 - "%s: agentx still has pending requests", __func__); 337 - #endif 329 + struct agentx_session *axs, *taxs; 330 + 331 + ax->ax_free = 0; 332 + 333 + TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions, taxs) 334 + agentx_session_free_finalize(axs); 335 + 336 + if (!TAILQ_EMPTY(&(ax->ax_sessions)) || 337 + !RB_EMPTY(&(ax->ax_requests)) || 338 + ax->ax_dstate != AX_DSTATE_CLOSE) 339 + return; 338 340 339 341 ax_free(ax->ax_ax); 340 342 ax->ax_nofd(ax, ax->ax_cookie, 1); ··· 477 479 struct agentx_session *axs = cookie; 478 480 struct agentx *ax = axs->axs_ax; 479 481 struct agentx_context *axc, *tsac; 482 + int axfree = ax->ax_free; 480 483 481 484 #ifdef AX_DEBUG 482 485 if (axs->axs_cstate != AX_CSTATE_WAITCLOSE) ··· 492 495 } 493 496 494 497 axs->axs_cstate = AX_CSTATE_CLOSE; 498 + ax->ax_free = 1; 495 499 496 500 agentx_log_axs_info(axs, "closed"); 497 501 498 502 TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, tsac) 499 503 agentx_context_reset(axc); 500 504 501 - if (axs->axs_dstate == AX_DSTATE_CLOSE) 502 - agentx_session_free_finalize(axs); 503 - else { 504 - if (ax->ax_cstate == AX_CSTATE_OPEN) 505 - if (agentx_session_start(axs) == -1) 506 - return -1; 507 - } 505 + if (ax->ax_cstate == AX_CSTATE_OPEN && 506 + axs->axs_dstate == AX_DSTATE_OPEN) 507 + agentx_session_start(axs); 508 + if (!axfree) 509 + agentx_free_finalize(ax); 510 + 508 511 return 0; 509 512 } 510 513 ··· 512 515 agentx_session_free(struct agentx_session *axs) 513 516 { 514 517 struct agentx_context *axc, *tsac; 518 + struct agentx *ax; 519 + int axfree; 515 520 516 521 if (axs == NULL) 517 522 return; 518 523 524 + ax = axs->axs_ax; 525 + axfree = ax->ax_free; 526 + ax->ax_free = 1; 527 + 519 528 if (axs->axs_dstate == AX_DSTATE_CLOSE) 520 529 agentx_log_axs_fatalx(axs, "%s: double free", __func__); 521 530 ··· 529 538 agentx_context_free(axc); 530 539 } 531 540 532 - if (axs->axs_cstate == AX_CSTATE_CLOSE) 533 - agentx_session_free_finalize(axs); 541 + if (!axfree) 542 + agentx_free_finalize(ax); 534 543 } 535 544 536 545 static void 537 546 agentx_session_free_finalize(struct agentx_session *axs) 538 547 { 539 548 struct agentx *ax = axs->axs_ax; 549 + struct agentx_context *axc, *taxc; 540 550 541 - #ifdef AX_DEBUG 542 - if (axs->axs_cstate != AX_CSTATE_CLOSE) 543 - agentx_log_axs_fatalx(axs, "%s: free without closing", 544 - __func__); 545 - if (!TAILQ_EMPTY(&(axs->axs_contexts))) 546 - agentx_log_axs_fatalx(axs, 547 - "%s: agentx still has contexts", __func__); 548 - #endif 551 + TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, taxc) 552 + agentx_context_free_finalize(axc); 553 + 554 + if (!TAILQ_EMPTY(&(axs->axs_contexts)) || 555 + axs->axs_cstate != AX_CSTATE_CLOSE || 556 + axs->axs_dstate != AX_DSTATE_CLOSE) 557 + return; 549 558 550 559 TAILQ_REMOVE(&(ax->ax_sessions), axs, axs_ax_sessions); 551 560 free(axs->axs_descr.aos_string); 552 561 free(axs); 553 - 554 - if (TAILQ_EMPTY(&(ax->ax_sessions)) && ax->ax_dstate == AX_DSTATE_CLOSE) 555 - agentx_free_finalize(ax); 556 562 } 557 563 558 564 static void 559 565 agentx_session_reset(struct agentx_session *axs) 560 566 { 561 567 struct agentx_context *axc, *tsac; 568 + struct agentx *ax = axs->axs_ax; 569 + int axfree = ax->ax_free; 570 + 571 + ax->ax_free = 1; 562 572 563 573 axs->axs_cstate = AX_CSTATE_CLOSE; 564 574 565 575 TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, tsac) 566 576 agentx_context_reset(axc); 567 577 568 - if (axs->axs_dstate == AX_DSTATE_CLOSE) 569 - agentx_session_free_finalize(axs); 578 + if (!axfree) 579 + agentx_free_finalize(ax); 570 580 } 571 581 572 582 struct agentx_context * ··· 714 724 agentx_context_free_finalize(struct agentx_context *axc) 715 725 { 716 726 struct agentx_session *axs = axc->axc_axs; 727 + struct agentx_region *axr, *taxr; 728 + struct agentx_agentcaps *axa, *taxa; 729 + 730 + TAILQ_FOREACH_SAFE(axa, &(axc->axc_agentcaps), axa_axc_agentcaps, taxa) 731 + agentx_agentcaps_free_finalize(axa); 732 + TAILQ_FOREACH_SAFE(axr, &(axc->axc_regions), axr_axc_regions, taxr) 733 + agentx_region_free_finalize(axr); 717 734 718 - #ifdef AX_DEBUG 719 - if (axc->axc_dstate != AX_DSTATE_CLOSE) 720 - agentx_log_axc_fatalx(axc, "%s: unexpected context free", 721 - __func__); 722 - #endif 723 735 if (!TAILQ_EMPTY(&(axc->axc_regions)) || 724 - !TAILQ_EMPTY(&(axc->axc_agentcaps))) 736 + !TAILQ_EMPTY(&(axc->axc_agentcaps)) || 737 + axc->axc_cstate != AX_CSTATE_CLOSE || 738 + axc->axc_dstate != AX_DSTATE_CLOSE) 725 739 return; 740 + 726 741 TAILQ_REMOVE(&(axs->axs_contexts), axc, axc_axs_contexts); 727 742 free(axc->axc_name.aos_string); 728 743 free(axc); ··· 733 748 { 734 749 struct agentx_agentcaps *axa, *tsaa; 735 750 struct agentx_region *axr, *tsar; 751 + struct agentx *ax = axc->axc_axs->axs_ax; 752 + int axfree = ax->ax_free; 753 + 754 + ax->ax_free = 1; 736 755 737 756 axc->axc_cstate = AX_CSTATE_CLOSE; 738 757 axc->axc_sysuptimespec.tv_sec = 0; ··· 743 762 TAILQ_FOREACH_SAFE(axr, &(axc->axc_regions), axr_axc_regions, tsar) 744 763 agentx_region_reset(axr); 745 764 746 - if (axc->axc_dstate == AX_DSTATE_CLOSE) 747 - agentx_context_free_finalize(axc); 765 + if (!axfree) 766 + agentx_free_finalize(ax); 748 767 } 749 768 750 769 struct agentx_agentcaps * ··· 883 902 struct agentx_context *axc = axa->axa_axc; 884 903 struct agentx_session *axs = axc->axc_axs; 885 904 struct agentx *ax = axs->axs_ax; 905 + int axfree = ax->ax_free; 886 906 887 907 #ifdef AX_DEBUG 888 908 if (axa->axa_cstate != AX_CSTATE_WAITCLOSE) ··· 899 919 } 900 920 901 921 axa->axa_cstate = AX_CSTATE_CLOSE; 922 + ax->ax_free = 1; 902 923 903 924 agentx_log_axc_info(axc, "agentcaps %s: closed", 904 925 ax_oid2string(&(axa->axa_oid))); 905 926 906 - if (axa->axa_dstate == AX_DSTATE_CLOSE) { 907 - agentx_agentcaps_free_finalize(axa); 908 - return 0; 909 - } else { 910 - if (axc->axc_cstate == AX_CSTATE_OPEN) { 911 - if (agentx_agentcaps_start(axa) == -1) 912 - return -1; 913 - } 914 - } 927 + if (axc->axc_cstate == AX_CSTATE_OPEN && 928 + axa->axa_dstate == AX_DSTATE_OPEN) 929 + agentx_agentcaps_start(axa); 930 + 931 + if (!axfree) 932 + agentx_free_finalize(ax); 915 933 return 0; 916 934 } 917 935 918 936 void 919 937 agentx_agentcaps_free(struct agentx_agentcaps *axa) 920 938 { 939 + struct agentx *ax = axa->axa_axc->axc_axs->axs_ax; 940 + int axfree; 941 + 921 942 if (axa == NULL) 922 943 return; 923 944 945 + axfree = ax->ax_free; 946 + ax->ax_free = 1; 947 + 924 948 if (axa->axa_dstate == AX_DSTATE_CLOSE) 925 949 agentx_log_axc_fatalx(axa->axa_axc, "%s: double free", 926 950 __func__); 927 951 928 952 axa->axa_dstate = AX_DSTATE_CLOSE; 929 953 930 - if (axa->axa_cstate == AX_CSTATE_OPEN) { 931 - if (agentx_agentcaps_close(axa) == -1) 932 - return; 933 - } 954 + if (axa->axa_cstate == AX_CSTATE_OPEN) 955 + agentx_agentcaps_close(axa); 934 956 935 - if (axa->axa_cstate == AX_CSTATE_CLOSE) 936 - agentx_agentcaps_free_finalize(axa); 957 + if (!axfree) 958 + agentx_free_finalize(ax); 937 959 } 938 960 939 961 static void ··· 941 963 { 942 964 struct agentx_context *axc = axa->axa_axc; 943 965 944 - #ifdef AX_DEBUG 945 966 if (axa->axa_dstate != AX_DSTATE_CLOSE || 946 967 axa->axa_cstate != AX_CSTATE_CLOSE) 947 - agentx_log_axc_fatalx(axc, "%s: unexpected free", __func__); 948 - #endif 968 + return; 949 969 950 970 TAILQ_REMOVE(&(axc->axc_agentcaps), axa, axa_axc_agentcaps); 951 971 free(axa->axa_descr.aos_string); 952 972 free(axa); 953 - 954 - if (axc->axc_dstate == AX_DSTATE_CLOSE) 955 - agentx_context_free_finalize(axc); 956 973 } 957 974 958 975 static void 959 976 agentx_agentcaps_reset(struct agentx_agentcaps *axa) 960 977 { 978 + struct agentx *ax = axa->axa_axc->axc_axs->axs_ax; 979 + 961 980 axa->axa_cstate = AX_CSTATE_CLOSE; 962 981 963 - if (axa->axa_dstate == AX_DSTATE_CLOSE) 964 - agentx_agentcaps_free_finalize(axa); 982 + if (!ax->ax_free) 983 + agentx_free_finalize(ax); 965 984 } 966 985 967 986 struct agentx_region * ··· 1166 1185 struct agentx_context *axc = axr->axr_axc; 1167 1186 struct agentx_session *axs = axc->axc_axs; 1168 1187 struct agentx *ax = axs->axs_ax; 1188 + int axfree = ax->ax_free; 1169 1189 1170 1190 #ifdef AX_DEBUG 1171 1191 if (axr->axr_cstate != AX_CSTATE_WAITCLOSE) ··· 1181 1201 return -1; 1182 1202 } 1183 1203 1204 + ax->ax_free = 1; 1184 1205 axr->axr_priority = AX_PRIORITY_DEFAULT; 1185 1206 axr->axr_cstate = AX_CSTATE_CLOSE; 1186 1207 1187 1208 agentx_log_axc_info(axc, "region %s: closed", 1188 1209 ax_oid2string(&(axr->axr_oid))); 1189 1210 1190 - if (axr->axr_dstate == AX_DSTATE_CLOSE) { 1191 - agentx_region_free_finalize(axr); 1192 - return 0; 1193 - } else { 1194 - if (axc->axc_cstate == AX_CSTATE_OPEN) { 1195 - if (agentx_region_start(axr) == -1) 1196 - return -1; 1197 - } 1198 - } 1211 + if (axc->axc_cstate == AX_CSTATE_OPEN && 1212 + axr->axr_dstate == AX_DSTATE_OPEN) 1213 + agentx_region_start(axr); 1214 + 1215 + if (!axfree) 1216 + agentx_free_finalize(ax); 1199 1217 return 0; 1200 1218 } 1201 1219 ··· 1204 1222 { 1205 1223 struct agentx_index *axi, *tsai; 1206 1224 struct agentx_object *axo, *tsao; 1225 + struct agentx *ax; 1226 + int axfree; 1207 1227 1208 1228 if (axr == NULL) 1209 1229 return; 1230 + 1231 + ax = axr->axr_axc->axc_axs->axs_ax; 1232 + axfree = ax->ax_free; 1233 + ax->ax_free = 1; 1210 1234 1211 1235 if (axr->axr_dstate == AX_DSTATE_CLOSE) 1212 1236 agentx_log_axc_fatalx(axr->axr_axc, "%s: double free", ··· 1224 1248 agentx_object_free(axo); 1225 1249 } 1226 1250 1227 - if (axr->axr_cstate == AX_CSTATE_OPEN) { 1228 - if (agentx_region_close(axr) == -1) 1229 - return; 1230 - } 1251 + if (axr->axr_cstate == AX_CSTATE_OPEN) 1252 + agentx_region_close(axr); 1231 1253 1232 - if (axr->axr_cstate == AX_CSTATE_CLOSE) 1233 - agentx_region_free_finalize(axr); 1254 + if (!axfree) 1255 + agentx_free_finalize(ax); 1234 1256 } 1235 1257 1236 1258 static void 1237 1259 agentx_region_free_finalize(struct agentx_region *axr) 1238 1260 { 1239 1261 struct agentx_context *axc = axr->axr_axc; 1262 + struct agentx_index *axi, *taxi; 1263 + struct agentx_object *axo, *taxo; 1240 1264 1241 - #ifdef AX_DEBUG 1242 - if (axr->axr_dstate != AX_DSTATE_CLOSE) 1243 - agentx_log_axc_fatalx(axc, "%s: unexpected free", __func__); 1244 - #endif 1265 + TAILQ_FOREACH_SAFE(axo, &(axr->axr_objects), axo_axr_objects, taxo) 1266 + agentx_object_free_finalize(axo); 1267 + TAILQ_FOREACH_SAFE(axi, &(axr->axr_indices), axi_axr_indices, taxi) 1268 + agentx_index_free_finalize(axi); 1245 1269 1246 1270 if (!TAILQ_EMPTY(&(axr->axr_indices)) || 1247 - !TAILQ_EMPTY(&(axr->axr_objects))) 1248 - return; 1249 - 1250 - if (axr->axr_cstate != AX_CSTATE_CLOSE) 1271 + !TAILQ_EMPTY(&(axr->axr_objects)) || 1272 + axr->axr_cstate != AX_CSTATE_CLOSE || 1273 + axr->axr_dstate != AX_DSTATE_CLOSE) 1251 1274 return; 1252 1275 1253 1276 TAILQ_REMOVE(&(axc->axc_regions), axr, axr_axc_regions); 1254 1277 free(axr); 1255 - 1256 - if (axc->axc_dstate == AX_DSTATE_CLOSE) 1257 - agentx_context_free_finalize(axc); 1258 1278 } 1259 1279 1260 1280 static void ··· 1262 1282 { 1263 1283 struct agentx_index *axi, *tsai; 1264 1284 struct agentx_object *axo, *tsao; 1285 + struct agentx *ax = axr->axr_axc->axc_axs->axs_ax; 1286 + int axfree = ax->ax_free; 1265 1287 1266 1288 axr->axr_cstate = AX_CSTATE_CLOSE; 1267 1289 axr->axr_priority = AX_PRIORITY_DEFAULT; 1290 + ax->ax_free = 1; 1268 1291 1269 1292 TAILQ_FOREACH_SAFE(axi, &(axr->axr_indices), axi_axr_indices, tsai) 1270 1293 agentx_index_reset(axi); 1271 1294 TAILQ_FOREACH_SAFE(axo, &(axr->axr_objects), axo_axr_objects, tsao) 1272 1295 agentx_object_reset(axo); 1273 1296 1274 - if (axr->axr_dstate == AX_DSTATE_CLOSE) 1275 - agentx_region_free_finalize(axr); 1297 + if (!axfree) 1298 + agentx_free_finalize(ax); 1276 1299 } 1277 1300 1278 1301 struct agentx_index * ··· 1739 1762 { 1740 1763 size_t i; 1741 1764 struct agentx_object *axo; 1765 + struct agentx *ax; 1766 + int axfree; 1742 1767 1743 1768 if (axi == NULL) 1744 1769 return; 1770 + 1771 + ax = axi->axi_axr->axr_axc->axc_axs->axs_ax; 1772 + axfree = ax->ax_free; 1773 + ax->ax_free = 1; 1745 1774 1746 1775 if (axi->axi_dstate == AX_DSTATE_CLOSE) 1747 1776 agentx_log_axc_fatalx(axi->axi_axr->axr_axc, ··· 1761 1790 1762 1791 if (axi->axi_cstate == AX_CSTATE_OPEN) 1763 1792 (void) agentx_index_close(axi); 1764 - else if (axi->axi_cstate == AX_CSTATE_CLOSE) 1765 - agentx_index_free_finalize(axi); 1793 + if (!axfree) 1794 + agentx_free_finalize(ax); 1766 1795 } 1767 1796 1768 1797 static void ··· 1770 1799 { 1771 1800 struct agentx_region *axr = axi->axi_axr; 1772 1801 1773 - #ifdef AX_DEBUG 1774 - if (axi->axi_dstate != AX_DSTATE_CLOSE) 1775 - agentx_log_axc_fatalx(axr->axr_axc, "%s: unexpected free", 1776 - __func__); 1777 - if (axi->axi_cstate != AX_CSTATE_CLOSE) 1778 - agentx_log_axc_fatalx(axr->axr_axc, 1779 - "%s: free without deallocating", __func__); 1780 - #endif 1781 - 1782 - if (axi->axi_objectlen != 0) 1802 + if (axi->axi_cstate != AX_CSTATE_CLOSE || 1803 + axi->axi_dstate != AX_DSTATE_CLOSE || 1804 + axi->axi_objectlen != 0) 1783 1805 return; 1784 1806 1785 1807 TAILQ_REMOVE(&(axr->axr_indices), axi, axi_axr_indices); 1786 1808 ax_varbind_free(&(axi->axi_vb)); 1787 1809 free(axi->axi_object); 1788 1810 free(axi); 1789 - if (axr->axr_dstate == AX_DSTATE_CLOSE) 1790 - agentx_region_free_finalize(axr); 1791 1811 } 1792 1812 1793 1813 static void 1794 1814 agentx_index_reset(struct agentx_index *axi) 1795 1815 { 1816 + struct agentx *ax = axi->axi_axr->axr_axc->axc_axs->axs_ax; 1817 + 1796 1818 axi->axi_cstate = AX_CSTATE_CLOSE; 1797 1819 1798 - if (axi->axi_dstate == AX_DSTATE_CLOSE) 1799 - agentx_index_free_finalize(axi); 1820 + if (!ax->ax_free) 1821 + agentx_free_finalize(ax); 1800 1822 } 1801 1823 1802 1824 static int ··· 1842 1864 struct agentx_session *axs = axc->axc_axs; 1843 1865 struct agentx *ax = axs->axs_ax; 1844 1866 struct ax_pdu_response *resp = &(pdu->ap_payload.ap_response); 1867 + int axfree = ax->ax_free; 1845 1868 1846 1869 #ifdef AX_DEBUG 1847 1870 if (axi->axi_cstate != AX_CSTATE_WAITCLOSE) ··· 1895 1918 } 1896 1919 1897 1920 axi->axi_cstate = AX_CSTATE_CLOSE; 1921 + ax->ax_free = 1; 1898 1922 1899 1923 agentx_log_axc_info(axc, "index %s: deallocated", 1900 1924 ax_oid2string(&(axi->axi_vb.avb_oid))); 1901 1925 1902 - if (axi->axi_dstate == AX_DSTATE_CLOSE) { 1903 - agentx_index_free_finalize(axi); 1904 - } else if (axr->axr_cstate == AX_CSTATE_OPEN) { 1905 - if (agentx_index_start(axi) == -1) 1906 - return -1; 1907 - } 1926 + if (axr->axr_cstate == AX_CSTATE_OPEN && 1927 + axi->axi_dstate == AX_DSTATE_OPEN) 1928 + agentx_index_start(axi); 1929 + 1930 + if (!axfree) 1931 + agentx_free_finalize(ax); 1908 1932 return 0; 1909 1933 } 1910 1934 ··· 2198 2222 agentx_log_axc_info(axc, "object %s (%s %s): %s", 2199 2223 oids, flags ? "instance" : "region", ax_oid2string(&oid), 2200 2224 ax_error2string(pdu->ap_payload.ap_response.ap_error)); 2201 - if (axo->axo_dstate == AX_DSTATE_CLOSE) 2202 - return agentx_object_close_finalize(NULL, axo); 2203 2225 return 0; 2204 2226 } 2205 2227 axo->axo_cstate = AX_CSTATE_OPEN; ··· 2227 2249 static void 2228 2250 agentx_object_unlock(struct agentx_object *axo) 2229 2251 { 2252 + struct agentx *ax = axo->axo_axr->axr_axc->axc_axs->axs_ax; 2253 + 2230 2254 #ifdef AX_DEBUG 2231 2255 if (axo->axo_lock == 0) 2232 2256 agentx_log_axc_fatalx(axo->axo_axr->axr_axc, 2233 2257 "%s: axo_lock == 0", __func__); 2234 2258 #endif 2235 2259 axo->axo_lock--; 2236 - if (axo->axo_lock == 0 && axo->axo_dstate == AX_DSTATE_CLOSE && 2237 - axo->axo_cstate == AX_CSTATE_CLOSE) 2238 - agentx_object_free_finalize(axo); 2260 + if (axo->axo_lock == 0) { 2261 + if (!ax->ax_free) 2262 + agentx_free_finalize(ax); 2263 + } 2239 2264 } 2240 2265 2241 2266 static int ··· 2316 2341 char oids[1024]; 2317 2342 uint8_t flags = 1; 2318 2343 size_t i; 2344 + int axfree = ax->ax_free; 2319 2345 2320 2346 #ifdef AX_DEBUG 2321 2347 if (axo->axo_cstate != AX_CSTATE_WAITCLOSE) ··· 2355 2381 flags ? "instance" : "region", ax_oid2string(&oid)); 2356 2382 } 2357 2383 2358 - if (axo->axo_dstate == AX_DSTATE_CLOSE) 2359 - agentx_object_free_finalize(axo); 2360 - else { 2361 - if (axr->axr_cstate == AX_CSTATE_OPEN) 2362 - if (agentx_object_start(axo) == -1) 2363 - return -1; 2364 - } 2384 + ax->ax_free = 1; 2385 + if (axr->axr_cstate == AX_CSTATE_OPEN && 2386 + axo->axo_dstate == AX_DSTATE_OPEN) 2387 + agentx_object_start(axo); 2388 + 2389 + if (!axfree) 2390 + agentx_free_finalize(ax); 2365 2391 2366 2392 return 0; 2367 2393 } ··· 2369 2395 void 2370 2396 agentx_object_free(struct agentx_object *axo) 2371 2397 { 2398 + struct agentx *ax; 2399 + int axfree; 2400 + 2372 2401 if (axo == NULL) 2373 2402 return; 2374 2403 2404 + ax = axo->axo_axr->axr_axc->axc_axs->axs_ax; 2405 + axfree = ax->ax_free; 2406 + ax->ax_free = 1; 2407 + 2375 2408 if (axo->axo_dstate == AX_DSTATE_CLOSE) 2376 2409 agentx_log_axc_fatalx(axo->axo_axr->axr_axc, 2377 2410 "%s: double free", __func__); 2378 2411 2379 2412 axo->axo_dstate = AX_DSTATE_CLOSE; 2380 2413 2381 - if (axo->axo_cstate == AX_CSTATE_OPEN) { 2382 - if (agentx_object_close(axo) == -1) 2383 - return; 2384 - } 2385 - if (axo->axo_cstate == AX_CSTATE_CLOSE) 2386 - agentx_object_free_finalize(axo); 2414 + if (axo->axo_cstate == AX_CSTATE_OPEN) 2415 + agentx_object_close(axo); 2416 + if (!axfree) 2417 + agentx_free_finalize(ax); 2387 2418 } 2388 2419 2389 2420 static void ··· 2395 2426 size_t i, j; 2396 2427 int found; 2397 2428 2398 - #ifdef AX_DEBUG 2399 - if (axo->axo_dstate != AX_DSTATE_CLOSE) 2400 - agentx_log_axc_fatalx(axo->axo_axr->axr_axc, 2401 - "%s: unexpected free", __func__); 2402 - #endif 2403 - 2404 - if (axo->axo_lock != 0) { 2405 - #ifdef AX_DEBUG 2406 - if (TAILQ_EMPTY(&(ax->ax_getreqs))) 2407 - agentx_log_axc_fatalx(axo->axo_axr->axr_axc, 2408 - "%s: %s axo_lock == %u", __func__, 2409 - ax_oid2string(&(axo->axo_oid)), axo->axo_lock); 2410 - #endif 2429 + if (axo->axo_dstate != AX_DSTATE_CLOSE || 2430 + axo->axo_cstate != AX_CSTATE_CLOSE || 2431 + axo->axo_lock != 0) 2411 2432 return; 2412 - } 2413 2433 2414 2434 RB_REMOVE(axc_objects, &(axo->axo_axr->axr_axc->axc_objects), axo); 2415 2435 TAILQ_REMOVE(&(axo->axo_axr->axr_objects), axo, axo_axr_objects); ··· 2429 2449 "%s: object not found in index", __func__); 2430 2450 #endif 2431 2451 axo->axo_index[i]->axi_objectlen--; 2432 - if (axo->axo_index[i]->axi_dstate == AX_DSTATE_CLOSE && 2433 - axo->axo_index[i]->axi_cstate == AX_CSTATE_CLOSE) 2434 - agentx_index_free_finalize(axo->axo_index[i]); 2435 2452 } 2436 2453 2437 2454 free(axo); ··· 2440 2457 static void 2441 2458 agentx_object_reset(struct agentx_object *axo) 2442 2459 { 2460 + struct agentx *ax = axo->axo_axr->axr_axc->axc_axs->axs_ax; 2461 + 2443 2462 axo->axo_cstate = AX_CSTATE_CLOSE; 2444 2463 2445 - if (axo->axo_dstate == AX_DSTATE_CLOSE) 2446 - agentx_object_free_finalize(axo); 2464 + if (!ax->ax_free) 2465 + agentx_free_finalize(ax); 2447 2466 } 2448 2467 2449 2468 static int
+2 -1
lib/libagentx/agentx_internal.h
··· 1 - /* $OpenBSD: agentx_internal.h,v 1.2 2020/10/26 16:02:16 tb Exp $ */ 1 + /* $OpenBSD: agentx_internal.h,v 1.3 2021/10/23 14:39:35 martijn Exp $ */ 2 2 /* 3 3 * Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org> 4 4 * ··· 38 38 int ax_fd; 39 39 enum agentx_cstate ax_cstate; 40 40 enum agentx_dstate ax_dstate; 41 + int ax_free; /* Freeing already planned */ 41 42 struct ax *ax_ax; 42 43 TAILQ_HEAD(, agentx_session) ax_sessions; 43 44 TAILQ_HEAD(, agentx_get) ax_getreqs;