summaryrefslogtreecommitdiffstats
path: root/tests
Commit message (Collapse)AuthorAgeFilesLines
* add osmo_fsm_set_dealloc_ctx(), to help with use-after-freeNeels Hofmeyr2019-10-292-17/+3460
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a simpler and more general solution to the problem so far solved by osmo_fsm_term_safely(true). This extends use-after-free fixes to arbitrary functions, not only FSM instances during termination. The aim is to defer talloc_free() until back in the main loop. Rationale: I discovered an osmo-msc use-after-free crash from an invalid message, caused by this pattern: void event_action() { osmo_fsm_inst_dispatch(foo, FOO_EVENT, NULL); osmo_fsm_inst_dispatch(bar, BAR_EVENT, NULL); } Usually, FOO_EVENT takes successful action, and afterwards we also notify bar. However, in this particular case, FOO_EVENT caused failure, and the immediate error handling directly terminated and deallocated bar. In such a case, dispatching BAR_EVENT causes a use-after-free; this constituted a DoS vector just from sending messages that cause *any* failure during the first event dispatch. Instead, when this is enabled, we do not deallocate 'foo' until event_action() has returned back to the main loop. Test: duplicate fsm_dealloc_test.c using this, and print the number of items deallocated in each test loop, to ensure the feature works. We also verify that the deallocation safety works simply by fsm_dealloc_test.c not crashing. We should probably follow up by refusing event dispatch and state transitions for FSM instances that are terminating or already terminated: see I0adc13a1a998e953b6c850efa2761350dd07e03a. Change-Id: Ief4dba9ea587c9b4aea69993e965fbb20fb80e78
* gsm0508: add functions to calculate beginning of a blockPhilipp Maier2019-10-284-0/+441
| | | | | | | | | | | The calculation of the beginning of a block for TCH/F, TCH/H and FACCH can be challenging since those channels are affected by the diagonal interleaving of the TCH channels. However, GSM 05.02 Section 7 Table 1 of 5 specifies how the blocks are distributed over the TDMA frame interval. Lets add a mapping function that is based on that table Related: OS#3803 Change-Id: I3d71c66f8c401f5afbad9b1c86c24580dab9e0ce
* vty: Return error if cmd returns CMD_WARNING while reading cfg filePau Espin Pedrol2019-10-284-0/+28
| | | | | | | Otherwise bad configurations can easily sneak in and produce unexpected behavior. Change-Id: Ic9c1b566ec4a459f03e6319cf369691903cf9d00
* logging: Introduce mutex API to manage log_target in multi-thread envsPau Espin Pedrol2019-10-092-2/+3
| | | | | | | | | | | | | | | | | | | | log_enable_multithread() enables use of locks inside the implementation. Lock use is disabled by default, this way only multi-thread processes need to enable it and suffer related complexity/performance penalties. Locks are required around osmo_log_target_list and items inside it, since targets can be used, modified and deleted by different threads concurrently (for instance, user writing "logging disable" in VTY while another thread is willing to write into that target). Multithread apps and libraries aiming at being used in multithread apps should update their code to use the locks introduced here when containing code iterating over osmo_log_target_list explictly or implicitly by obtaining a log_target (eg. osmo_log_vty2tgt()). Related: OS#4088 Change-Id: Id7711893b34263baacac6caf4d489467053131bb
* tdef_test: verify case where osmo_tdef_set returns -EEXISTPau Espin Pedrol2019-10-072-0/+4
| | | | Change-Id: I436daa804aac11622fde24afe9ea35193d9e9beb
* tdef: Introduce min_val and max_val fieldsPau Espin Pedrol2019-10-074-3/+87
| | | | | | | | | | | This is useful for timers expected to have a range of valid or expected values. Validation is done at runtime when timer values are set by the app or by the user through the VTY. Related: OS#4190 Change-Id: I4661ac41c29a009a1d5fc57d87aaee6041c7d1b2
* gsup: add OSMO_GSUP_SUPPORTED_RAT_TYPES_IE and OSMO_GSUP_CURRENT_RAT_TYPE_IENeels Hofmeyr2019-09-281-7/+7
| | | | | | | | | | | | | | OSMO_GSUP_SUPPORTED_RAT_TYPES_IE corresponds to the Supported RAT Types Indicator from 3GPP TS 29.002. See 8.1.2 MAP_UPDATE_LOCATION service, which indicates the capabilities of the MSC/VLR to the HLR. So far, have room for eight RAT types in the gsup_msg. That is an arbitrary random choice without any rationale. OSMO_GSUP_CURRENT_RAT_TYPE_IE is useful to communicate the currently used RAN / RAT type of the current subscriber during Location Updating Request. Change-Id: I93850710ab55a605bf61b95063a69682a2899bb1
* gsm29205_test: fix error: missing braces around initializerVadim Yanitskiy2019-09-271-1/+7
| | | | | | | Since structure 'osmo_gcr_parsed' does contain arrays, GCC is not happy about the way we initialize it. Let's do it explicitly. Change-Id: Ia814b4a4ed5bec84ff1f69232f7f7d5ca0d19794
* No fail if no /proc/cpuinfoRuben Undheim2019-09-261-1/+1
| | | | Change-Id: I4b9e12e34f69d98fa87179c7ee390e31001ec943
* ecu_fr: increase test coverage for FR ECU implementationPhilipp Maier2019-09-202-0/+84
| | | | | | | | | | | | | The ECU implementation for FR is currently tested by calling the related functions directly and by using the generic ECU abstraction layer. However, the test "test_fr_concealment" only tests directly. Lets add a version that uses the generic ECU abstraction layer as well. The generic ECU abstraction layer obsolets the public API functions osmo_ecu_fr_reset() and osmo_ecu_fr_conceal(), lets tag those functions as dprecated. Change-Id: Ib0c8a9b164f14ea4fa00688f760a76cdb4890af4
* codec/ecu: Introduce new generic Error Concealment Unit abstractionHarald Welte2019-09-022-0/+223
| | | | | | | | | | | | | | | | | | | | We don't want to expose the details of a given ECU implementation to the user (e.g. osmo-bts), but have a generic abstraction layer where an ECU implementation can simply register a few call-back functions with the generic core. As the developer and copyright holder of the related code, I hereby state that any ECU implementation using 'struct osmo_ecu_ops' and registering with the 'osmo_ecu_register()' function shall not be considered as a derivative work under any applicable copyright law; the copyleft terms of GPLv2 shall hence not apply to any such ECU implementation. The intent of the above exception is to allow anyone to combine third party Error Concealment Unit implementations with libosmocore, including but not limited to such published by ETSI. Change-Id: I4d33c9c7c2d4c7462ff38a49c178b65accae1915
* context: Add support for [per-thread] global talloc contextsHarald Welte2019-08-274-0/+99
| | | | | | | | | | Rather than having applications maintain their own talloc cotexts, let's offer some root talloc contexts in libosmocore. Let's also make them per thread right from the beginning. This will help some multi-threaded applications to use talloc in a thread-safe way. Change-Id: Iae39cd57274bf6753ecaf186f229e582b42662e3
* add vty logp command to echo on all log targetsNeels Hofmeyr2019-08-131-0/+53
| | | | | | | | | | | | | | | | | | | | | | | | | | | When reading SUT logs resulting from TTCN3 runs, it can be hard to figure out which log section corresponds to which test code. Add a 'logp' command on VIEW and ENABLE nodes that simply echos an arbitrary message on log output, useful to set markers / explanations from the TTCN3 code, which then appear in all log outputs and can make it trivial to figure out which log section is interesting. logging_vty_test# logp lglobal notice This is the log message DLGLOBAL NOTICE This is the log message From TTCN3, could be used like this, e.g. in BSC_Tests.ttcn: private function f_logp(charstring log_msg) runs on MSC_ConnHdlr { // log on TTCN3 log output log(log_msg); // log in stderr log f_vty_transceive(BSCVTY, "logp lglobal notice " & log_msg); } ... f_logp("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure."); Change-Id: Ife5dc8999174c74e0d133729284fe526d6eaf8d9
* tests: logging: Remove undefined param passed to logging_vty_add_cmdsPau Espin Pedrol2019-08-051-1/+1
| | | | | | | | | | | Since March 15th 2017, libosmocore API logging_vty_add_cmds() had its parameter removed (c65c5b4ea075ef6cef11fff9442ae0b15c1d6af7). However, definition in C file doesn't contain "(void)", which means number of parameters is undefined and thus compiler doesn't complain. Let's remove parameters from all callers before enforcing "(void)" on it. Related: OS#4138 Change-Id: Iaea795521361a8e5b3b45eaeb35e6eda69163af3
* gsm0808_test: Fix wrong use of memcpPau Espin Pedrol2019-07-301-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | After recent system upgrade, gcc 9.1.0, I started getting gsm0808_test failing locally: Assert failed memcmp(&enc_ct, &dec_ct, sizeof(enc_ct)) == 0 libosmocore/tests/gsm0808/gsm0808_test.c:992 During investigation with gdb, fields of both structures seem to contain same values. However, closer lookup gives some hints on why it fails: (gdb) print memcmp(&enc_ct, &dec_ct, sizeof(enc_ct)) $1 = 85 (gdb) print memcmp(&enc_ct, &dec_ct, 12) $14 = 85 (gdb) print ((uint8_t*)&enc_ct)[11] $15 = 85 'U' (gdb) print ((uint8_t*)&dec_ct)[11] $16 = 0 '\000' So the 12th byte in struct gsm0808_channel_type is basically an alignment padding byte added by the compiler (to align perm_spch_len to 4-byte alignment). Since both compared structs are initialized without memset(0) but using compiler's designated initializers, it seems the compiler decided it's no longer needed to zero the padding byte, making memcp fail in this case. In order to avoid the failure, let's properly check every field instead of using memcp here. Change-Id: I17fe7a0a5dc650f050bba1f47d071be749550729
* utils.h: require a semi colon after OSMO_ASSERTAlexander Couzens2019-07-081-1/+1
| | | | | | | | | When using `OSMO_ASSERT(exp);` clang will warn about an empty expression because the semi colon was superflous. Use do {} while (0) to enfore the need of a semi colon. This might break other test. Change-Id: I2272d29a81496164bebd1696a694383a28a86434
* vty: command.c: Fix: single-choice optional args are no longer passed ↵Pau Espin Pedrol2019-06-141-1/+1
| | | | | | | | | | | incomplete to vty func For instance, take command "single0 [one]": If user executes "single0 on", VTY func will receive argv[0]="one" instead of argv[0]="on". Related: OS#4045 Change-Id: I5f4e2d16c62a2d22717989c6acc77450957168cb
* vty: command.c: Fix: multi-choice args are no longer passed incomplete to ↵Pau Espin Pedrol2019-06-142-11/+12
| | | | | | | | | | | vty func For instance, take command "multi0 (one|two|three)": If user executes "multi0 tw", VTY func will receive argv[0]="two" instead of argv[0]="tw". Fixes: OS#4045 Change-Id: I91b6621ac3d87fda5412a9b415e7bfb4736c8a9a
* vty: tests: Verify incomplete optional parameters are passed to vty funcsPau Espin Pedrol2019-06-142-0/+18
| | | | | | | | The test shows that in the case were "single0 on" is executed, VTY function should return complete "single0 one" but it doesn't. Related: OS#4045 Change-Id: Ib5b9dc07e2b280dc95011b3926afb1d490cadd81
* vty: command.c: Fix is_cmd_ambiguous() returning always 0Pau Espin Pedrol2019-06-112-38/+9
| | | | | | | | | | inner block defined variable "enum match_type ret" was being masking outter block variable "int ret = 0". The ret variable was being given non zero values only inside the inner block, so that change was done on the inner variable and not the outer one, which is returned. Fixes: 5314c513f23688462d7f7937e5ae5e0d5cd4548e Change-Id: Iec87d7db49a096d07e38ff8a060b923a52bfd6ba
* gsm48_decode_bcd_number2: fix ENOSPC edge caseOliver Smith2019-06-072-0/+15
| | | | | | | | | | | | | Return ENOSPC if the decoding buffer is one byte too small, instead of returning 0 and silently truncating the string. Add a new "truncated" variable to detect if the loop breaks in the final iteration. The string is not truncated if there is exactly one 0xf ('\0') higher nibble remaining. This is covered by the existing test case "long 15-digit (maximum) MSISDN, limited buffer". Related: OS#4049 Change-Id: Ie05900aca50cc7fe8a45d17844dbfcd905fd82fe
* vty_transcript_test.vty: add choice auto-complete testsVadim Yanitskiy2019-06-061-0/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch is a result of discussion we had in [1]. The key idea is that libosmovty should properly auto-complete the commands containing choice, such as the following one: multi0 (one|two|three) [1] If9b0c0d031477ca87786aab5c269d00748e896c8 Right now, sending the following command: (osmo-foo-bar)# multi0 th would basically match the following vector: multi0 three however the resulting argv would be: ["multi0", "th"] Moreover, sending the following command: (osmo-foo-bar)# multi0 t would basically match the following vectors: multi0 two multi0 three because both start from 't', so the resulting argv would be: ["multi0", "t"] which is ambiguous! The expected output is: (osmo-foo-bar)# multi0 th ok argc=1 three (osmo-foo-bar)# multi0 t % Ambiguous command. This is going to be fixed in the follow up patches. Change-Id: I83c3aef813173952641035862c534ef16384780e
* gsm48_encode_bcd_number(): clarify optional LHV header initializationVadim Yanitskiy2019-05-292-5/+9
| | | | Change-Id: Iafd911dd55691b3715391e3899cd6971245c8d7f
* gsm48_decode_bcd_number2(): return -EINVAL if LV has too big lengthVadim Yanitskiy2019-05-282-3/+3
| | | | Change-Id: Ie07b2e8bc2f9628904e88448b4ee63b359655123
* gsm48_decode_bcd_number2(): fix: return -ENOSPC on truncationVadim Yanitskiy2019-05-282-4/+4
| | | | | | | | The documentation of gsm48_decode_bcd_number2() clearly states that the output truncation is a erroneous case, so it should actually return negative in such cases. Let's return -ENOSPC. Change-Id: I75680f232001ba419a587fed4c24f32c70c3ad2b
* gsm48_decode_bcd_number2(): fix output truncationVadim Yanitskiy2019-05-281-2/+2
| | | | | | | | | | | | | | | | | Thanks to the new unit test for BCD number encoding / decoding, it was discovered that gsm48_decode_bcd_number2() does not properly handle encoded LV if the output buffer size is equal to the original MSISDN length + 1 (\0-terminator): one digit is lost. For example, decoding of 15-digit long MSISDN to a buffer of size 16 (15 digits + 1 for \0) would give us only 14 digits. The problem was that 'output_len' was being decremented before checking the remaining buffer length and writing a digit to it. As a result, the maximum length was always one byte shorter. Change-Id: I61d49387fedbf7b238e21540a5eff22f6861e27a Fixes: OS#4025
* gsm0408/gsm0408_test.c: introduce BCD number encoding / decoding testVadim Yanitskiy2019-05-282-0/+224
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | So far, both gsm48_encode_bcd_number() and gsm48_decode_bcd_number2() did not have any unit test coverage. Let's fill this gap by testing the following scenarios: - encoding / decoding of a regular 9-digit MSISDN; - encoding / decoding of a MSISDN with optional LHV; - encoding / decoding of a long 15-digit MSISDN; - encoding / decoding of a MSISDN to a buffer: - with exactly matching size, - with lower size (truncation); - decoding LV buffer with incorrect length, - encoding / decoding an empty input buffer. As it turns out, gsm48_decode_bcd_number2() does not properly handle encoded LV if the output buffer size is equal to the original MSISDN length + 1 (\0-terminator): one digit is lost. For example, decoding of 15-digit long MSISDN to a buffer of size 16 (15 digits + 1 for \0) would give us only 14 digits. This is reflected in the unit test output: Decoding HEX (buffer limit=16) '0821436587092143f5'... Expected: (rc=0) '123456789012345' Actual: (rc=0) '12345678901234' Moreover, if the output buffer is shorter than decoded number, gsm48_decode_bcd_number2() silently truncates it and returns 0, while its description states, that the rc should reflect this. To be fixed in the follow-up patches. Change-Id: I4b2c330cf8ffe4427c0bee7d5f3b74be56ecd85d Related: OS#4025
* oap_client: Fix license: GPLv2+ instead of AGPLv3+Harald Welte2019-05-271-4/+5
| | | | | | | | | | | | libosmo{core,gsm,vty} code is GPLv2+. The OAP code originated in osmo-msc.git and was moved here without changing the license. That was a mistake, it always was meant to be under GPLv2-or-later after moving to libosmocore.git. Copyright is with sysmocom, so I as the managing director can approve the license change. Change-Id: I08311fa8214c15f8df8945b9894226608cf96f15
* TLV: Add one-shot TLV encoderHarald Welte2019-05-192-0/+49
| | | | | | | | | | | | | | | | | So far, the TLV code contained two types of functions * tlp_parse() to parse all TLVs according to definition into tlvp_parsed * various helper functions to encode individual TLVs during message generation This patch implements the inverse of tlv_parse(): tlv_encode(), which takes a full 'struct tlv_pared' and encodes all IEs found in it. The order of IEs is in numerically ascending order of the tag. As many protocols have different IE/TLV ordering requirements, let's add a tlv_encode_ordered() function where the caller can specify the TLV ordering during the one-shot encode. Change-Id: I761a30bf20355a9f80a4a8e0c60b0b0f78515efe
* add osmo_stat_item_inc/osmo_stat_item_dec to set it relativeAlexander Couzens2019-05-071-0/+16
| | | | Change-Id: Id2462c4866bd22bc2338c9c8f69b775f88ae7511
* GSUP: add inter-MSC handover related msgs and IEsOliver Smith2019-04-263-4/+347
| | | | | | | | | | | | | | | | | | | | Based on a draft created by Neels, which is the result of reading a MAP trace of two MSCs negotiating inter-MSC handovers, and of reading the TS 29.002, TS 29.010 and related specs: https://lists.osmocom.org/pipermail/openbsc/2019-January/012653.html I figured out that the "Handover Number" mentioned in the specifications is the same as the MSISDN IE that we already have, so we can use that instead of creating a new IE (example usage in tests/gsup/gsup_test.c). Create a new OSMO_GSUP_MSGT_E_ROUTING_ERROR message type, which the GSUP server uses to tell a client that its message could not be forwarded to the destination (see [1]). MAP has no related message. [1]: Change-Id: Ia4f345abc877baaf0a8f73b8988e6514d9589bf5 (osmo-hlr.git) Related: OS#3774 Change-Id: Ic00b0601eacff6d72927cea51767801142ee75db
* GSUP: add Message Class IENeels Hofmeyr2019-04-132-5/+7
| | | | | | | | | | | | | | | | | | osmo-msc and osmo-hlr have distinct subsystems handling incoming GSUP messages. So far we decide entirely by message type which code path should handle a GSUP message. Thus no GSUP message type may be re-used across subsystems. If we add a GSUP message to indicate a routing error, it would have to be a distinct message type for subscriber management, another one for SMS, another one for USSD... To allow introducing common message types, introduce a GSUP Message Class IE. In the presence of this IE, GSUP handlers can trivially direct a received message to the right code path. If it is missing, handlers can fall back to the previous switch(message_type) method. Change-Id: Ic397a9f2c4a7224e47cab944c72e75ca5592efef
* add osmo_{escape,quote}_str_buf2() for standard args orderingNeels Hofmeyr2019-04-122-6/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | To be able to append an escaped or quoted string using OSMO_STRBUF_APPEND_NOLEN(), the function signature must have the buf and len as first args, like most other *_buf() functions. Add osmo_escape_str_buf2() and osmo_quote_str_buf2() to match this signature. A recent patch [1] has changed the return value of osmo_escape_str_buf() to char*, removing the const. However, the functions may return const strings, hence re-add the const. The new signatures always return the non-const buffer. To avoid code duplication, implement osmo_quote_str_buf() and osmo_escape_str_buf() by calling the new functions. I decided to allow slight changes to the behavior for current osmo_escape_str() and osmo_escape_str_buf(), because impact on callers is minimal: (1) The new implementation uses OSMO_STRBUF_*, and in consequence osmo_quote_str() no longer prints an ending double quote after truncated strings; Before, a truncated output was, sic: "this string is trunca" and now this becomes, sic: "this string is truncat I decided to not keep the old behavior because it is questionable to begin with. It looks like the string actually ended at the truncation boundary instead of the reason being not enough space in the output buffer. (2) The new osmo_escape_str_buf2() function obviously cannot pass-thru an unchanged char* if no escaping was needed. Sacrifice this tiny optimization feature to avoid code duplication: - it is an unnoticeable optimization, - the caller anyway always passes a string buffer, - the feature caused handling strings and buffers differently depending on their content (i.e. code that usually writes out strings in full length "suddenly" truncates because a non-printable character is contained, etc.) I considered adding a skip_if_unescaped flag to the osmo_quote_str_buf2() function signature, but in the end decided that the API clutter is not worth having for all the above reasons. Adjust tests to accomodate above changes. [1] 4a62eda225ab7f3c9556990c81a6fc5e19b5eec8 Ibf85f79e93244f53b2684ff6f1095c5b41203e05 Change-Id: Id748b906b0083b1f1887f2be7a53cae705a8a9ae
* tweak OSMO_STRBUF_APPEND(), add OSMO_STRBUF_APPEND_NOLEN()Neels Hofmeyr2019-04-112-0/+23
| | | | | | | | | | | | | In OSMO_STRBUF_APPEND, use local variable names that are less likely to shadow other local variables: prefix with _sb_. In OSMO_STRBUF_APPEND, add a check to add to .pos only if it is not NULL. Add OSMO_STRBUF_APPEND_NOLEN(), which works for function signatures that don't return a length. This is useful for any osmo_*_buf() string writing functions, so that these write directly to the strbuf. Change-Id: I108cadf72deb3a3bcab9a07e50572d9da1ab0359
* add osmo_str_startswith()Neels Hofmeyr2019-04-112-0/+43
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Move from a static implementation in tdef_vty.c to utils.c, I also want to use this in osmo-msc. The point is that the telnet VTY allows unambiguous partly matches of keyword args. For example, if I have a command definition of: compare (apples|oranges) then it is perfectly legal as for the vty parser to write only compare app One could expect the VTY to then pass the unambiguous match of "apples" to the parsing function, but that is not the case. Hence a VTY function implementation is faced with parsing a keyword of "app" instead of the expected "apples". This is actually a very widespread bug in our VTY implementations, which assume that exactly one full keyword will always be found. I am now writing new commands in a way that are able to manage only the starts of keywords. Arguably, strstr(a, b) == a does the same thing, but it searches the entire string unnecessarily. Change-Id: Ib2ffb0e9a870dd52e081c7e66d8818057d159513
* fsm_dealloc_test: no need for ST_DESTROYINGNeels Hofmeyr2019-04-112-1799/+1520
| | | | | | | | | | | | | | A separate ST_DESTROYING state originally helped with certain deallocation scenarios. But now that fsm.c avoids re-entering osmo_fsm_inst_term() twice and gracefully handles FSM instance deallocations for termination cascades, it is actually just as safe without a separate ST_DESTROYING state. ST_DESTROYING was used to flag deallocation and prevent entering osmo_fsm_inst_term() twice, which works only in a very limited range of scenarios. Remove ST_DESTROYING from fsm_dealloc_test.c to show that all tested scenarios still clean up gracefully. Change-Id: I05354e6cad9b82ba474fa50ffd41d481b3c697b4
* fsm: support graceful osmo_fsm_inst_term() cascadesNeels Hofmeyr2019-04-114-225/+3290
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add global flag osmo_fsm_term_safely() -- if set to true, enable the following behavior: Detect osmo_fsm_inst_term() occuring within osmo_fsm_inst_term(): - collect deallocations until the outermost osmo_fsm_inst_term() is done. - call osmo_fsm_inst_free() *after* dispatching the parent event. If a struct osmo_fsm_inst enters osmo_fsm_inst_term() while another is already within osmo_fsm_inst_term(), do not directly deallocate it, but talloc-reparent it to a separate talloc context, to be deallocated with the outermost FSM inst. The effect is that all osmo_fsm_inst freed within an osmo_fsm_inst_term() cascade will stay allocated until all osmo_fsm_inst_term() are complete and all of them will be deallocated at the same time. Mark the deferred deallocation state as __thread in an attempt to make cascaded deallocation handling threadsafe. Keep the enable/disable flag separate, so that it is global and not per-thread. The feature is showcased by fsm_dealloc_test.c: with this feature, all of those wild deallocation scenarios succeed. Make fsm_dealloc_test a normal regression test in testsuite.at. Rationale: It is difficult to gracefully handle deallocations of groups of FSM instances that reference each other. As soon as one child dispatching a cleanup event causes its parent to deallocate before fsm.c was ready for it, deallocation will hit a use-after-free. Before this patch, by using parent_term events and distinct "terminating" FSM states, parent/child FSMs can be taught to wait for all children to deallocate before deallocating the parent. But as soon as a non-child / non-parent FSM instance is involved, or actually any other cleanup() action that triggers parent FSMs or parent talloc contexts to become unused, it is near impossible to think of all possible deallocation events ricocheting, and to avoid running into freeing FSM instances that were still in the middle of osmo_fsm_inst_term(), or FSM instances to enter osmo_fsm_inst_term() more than once. This patch makes deallocation of "all possible" setups of complex cross referencing FSM instances easy to handle correctly, without running into use-after-free or double free situations, and, notably, without changing calling code. Change-Id: I8eda67540a1cd444491beb7856b9fcd0a3143b18
* fsm: add flag to ensure osmo_fsm_inst_term() happens only onceNeels Hofmeyr2019-04-111-38/+340
| | | | | | | | | | | To prevent re-entering osmo_fsm_inst_term() twice for the same osmo_fsm_inst, add flag osmo_fsm_inst.proc.terminating. osmo_fsm_inst_term() sets this to true, or exits i