From 89330ad407986dc900ceb69f86dc009a425132aa Mon Sep 17 00:00:00 2001 From: shikokuchuo <53399081+shikokuchuo@users.noreply.github.com> Date: Sun, 4 May 2025 17:00:35 +0100 Subject: [PATCH 1/9] Unify error paths for streams --- man/nanonext-package.Rd | 2 +- src/proto.c | 80 +++++++++++++++-------------------------- 2 files changed, 30 insertions(+), 52 deletions(-) diff --git a/man/nanonext-package.Rd b/man/nanonext-package.Rd index aa78b48f1..36922bb8c 100644 --- a/man/nanonext-package.Rd +++ b/man/nanonext-package.Rd @@ -94,7 +94,7 @@ Useful links: } \author{ -\strong{Maintainer}: Charlie Gao \email{charlie.gao@posit.co} (\href{https://orcid.org/0000-0002-0750-061X}{ORCID}) +\strong{Maintainer}: Charlie Gao \email{charlie.gao@shikokuchuo.net} (\href{https://orcid.org/0000-0002-0750-061X}{ORCID}) Other contributors: \itemize{ diff --git a/src/proto.c b/src/proto.c index 071cecc6d..42c647cda 100644 --- a/src/proto.c +++ b/src/proto.c @@ -193,35 +193,31 @@ static SEXP nano_stream_dial(SEXP url, SEXP textframes, SEXP tls) { NANO_ENSURE_ALLOC(nst); nst->mode = NANO_STREAM_DIALER; nst->textframes = NANO_INTEGER(textframes) != 0; - nng_url *up; - nng_aio *aiop; + nng_url *up = NULL; + nng_aio *aiop = NULL; int xc; SEXP sd; - if ((xc = nng_url_parse(&up, add))) - goto exitlevel1; - - xc = nng_stream_dialer_alloc_url(&nst->endpoint.dial, up); - if (xc) - goto exitlevel2; + if ((xc = nng_url_parse(&up, add)) || + (xc = nng_stream_dialer_alloc_url(&nst->endpoint.dial, up)) || + (xc = nng_aio_alloc(&aiop, NULL, NULL))) + goto fail; if (!strcmp(up->u_scheme, "ws") || !strcmp(up->u_scheme, "wss")) { if (nst->textframes && ((xc = nng_stream_dialer_set_bool(nst->endpoint.dial, "ws:recv-text", 1)) || (xc = nng_stream_dialer_set_bool(nst->endpoint.dial, "ws:send-text", 1)))) - goto exitlevel3; + goto fail; } if (!strcmp(up->u_scheme, "wss")) { if (tls == R_NilValue) { - if ((xc = nng_tls_config_alloc(&nst->tls, NNG_TLS_MODE_CLIENT))) - goto exitlevel3; - - if ((xc = nng_tls_config_server_name(nst->tls, up->u_hostname)) || + if ((xc = nng_tls_config_alloc(&nst->tls, NNG_TLS_MODE_CLIENT)) || + (xc = nng_tls_config_server_name(nst->tls, up->u_hostname)) || (xc = nng_tls_config_auth_mode(nst->tls, NNG_TLS_AUTH_MODE_NONE)) || (xc = nng_stream_dialer_set_ptr(nst->endpoint.dial, NNG_OPT_TLS_CONFIG, nst->tls))) - goto exitlevel4; + goto fail; } else { nst->tls = (nng_tls_config *) NANO_PTR(tls); @@ -229,18 +225,15 @@ static SEXP nano_stream_dial(SEXP url, SEXP textframes, SEXP tls) { if ((xc = nng_tls_config_server_name(nst->tls, up->u_hostname)) || (xc = nng_stream_dialer_set_ptr(nst->endpoint.dial, NNG_OPT_TLS_CONFIG, nst->tls))) - goto exitlevel4; + goto fail; } } - if ((xc = nng_aio_alloc(&aiop, NULL, NULL))) - goto exitlevel4; - nng_stream_dialer_dial(nst->endpoint.dial, aiop); nng_aio_wait(aiop); if ((xc = nng_aio_result(aiop))) - goto exitlevel5; + goto fail; nst->stream = nng_aio_get_output(aiop, 0); @@ -258,16 +251,12 @@ static SEXP nano_stream_dial(SEXP url, SEXP textframes, SEXP tls) { UNPROTECT(1); return sd; - exitlevel5: - nng_aio_free(aiop); - exitlevel4: + fail: if (nst->tls != NULL) nng_tls_config_free(nst->tls); - exitlevel3: + nng_aio_free(aiop); nng_stream_dialer_free(nst->endpoint.dial); - exitlevel2: nng_url_free(up); - exitlevel1: free(nst); ERROR_OUT(xc); @@ -282,34 +271,30 @@ static SEXP nano_stream_listen(SEXP url, SEXP textframes, SEXP tls) { NANO_ENSURE_ALLOC(nst); nst->mode = NANO_STREAM_LISTENER; nst->textframes = NANO_INTEGER(textframes) != 0; - nng_url *up; - nng_aio *aiop; + nng_url *up = NULL; + nng_aio *aiop = NULL; int xc; SEXP sl; - if ((xc = nng_url_parse(&up, add))) - goto exitlevel1; - - xc = nng_stream_listener_alloc_url(&nst->endpoint.list, up); - if (xc) - goto exitlevel2; + if ((xc = nng_url_parse(&up, add)) || + (xc = nng_stream_listener_alloc_url(&nst->endpoint.list, up)) || + (xc = nng_aio_alloc(&aiop, NULL, NULL))) + goto fail; if (!strcmp(up->u_scheme, "ws") || !strcmp(up->u_scheme, "wss")) { if (nst->textframes && ((xc = nng_stream_listener_set_bool(nst->endpoint.list, "ws:recv-text", 1)) || (xc = nng_stream_listener_set_bool(nst->endpoint.list, "ws:send-text", 1)))) - goto exitlevel3; + goto fail; } if (!strcmp(up->u_scheme, "wss")) { if (tls == R_NilValue) { - if ((xc = nng_tls_config_alloc(&nst->tls, NNG_TLS_MODE_SERVER))) - goto exitlevel3; - - if ((xc = nng_tls_config_auth_mode(nst->tls, NNG_TLS_AUTH_MODE_NONE)) || + if ((xc = nng_tls_config_alloc(&nst->tls, NNG_TLS_MODE_SERVER)) || + (xc = nng_tls_config_auth_mode(nst->tls, NNG_TLS_AUTH_MODE_NONE)) || (xc = nng_stream_listener_set_ptr(nst->endpoint.list, NNG_OPT_TLS_CONFIG, nst->tls))) - goto exitlevel4; + goto fail; } else { nst->tls = (nng_tls_config *) NANO_PTR(tls); @@ -317,21 +302,18 @@ static SEXP nano_stream_listen(SEXP url, SEXP textframes, SEXP tls) { if ((xc = nng_tls_config_server_name(nst->tls, up->u_hostname)) || (xc = nng_stream_listener_set_ptr(nst->endpoint.list, NNG_OPT_TLS_CONFIG, nst->tls))) - goto exitlevel4; + goto fail; } } if ((xc = nng_stream_listener_listen(nst->endpoint.list))) - goto exitlevel4; - - if ((xc = nng_aio_alloc(&aiop, NULL, NULL))) - goto exitlevel4; + goto fail; nng_stream_listener_accept(nst->endpoint.list, aiop); nng_aio_wait(aiop); if ((xc = nng_aio_result(aiop))) - goto exitlevel5; + goto fail; nst->stream = nng_aio_get_output(aiop, 0); @@ -349,16 +331,12 @@ static SEXP nano_stream_listen(SEXP url, SEXP textframes, SEXP tls) { UNPROTECT(1); return sl; - exitlevel5: - nng_aio_free(aiop); - exitlevel4: + fail: if (nst->tls != NULL) nng_tls_config_free(nst->tls); - exitlevel3: + nng_aio_free(aiop); nng_stream_listener_free(nst->endpoint.list); - exitlevel2: nng_url_free(up); - exitlevel1: free(nst); ERROR_OUT(xc); From 7e167aaba2c51395f6b31789025ee52661de11b7 Mon Sep 17 00:00:00 2001 From: shikokuchuo <53399081+shikokuchuo@users.noreply.github.com> Date: Sun, 4 May 2025 17:15:08 +0100 Subject: [PATCH 2/9] Consistent error paths for IP code --- src/net.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/net.c b/src/net.c index 5d9613106..498f72ce8 100644 --- a/src/net.c +++ b/src/net.c @@ -25,8 +25,7 @@ SEXP rnng_ip_addr(void) { int j = 0; do { addrs = malloc(bufsize); - if (addrs == NULL) - goto exitlevel1; + NANO_ENSURE_ALLOC(addrs); ret = GetAdaptersAddresses(AF_INET, flags, NULL, addrs, &bufsize); if (ret == ERROR_BUFFER_OVERFLOW) @@ -35,7 +34,7 @@ SEXP rnng_ip_addr(void) { if (ret != NO_ERROR) { free(addrs); - goto exitlevel1; + goto cleanup; } for (adapter = addrs; adapter != NULL; adapter = adapter->Next) { @@ -65,7 +64,7 @@ SEXP rnng_ip_addr(void) { struct ifaddrs *ifaddr, *ifa; if (getifaddrs(&ifaddr)) - goto exitlevel1; + goto cleanup; for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { @@ -90,7 +89,7 @@ SEXP rnng_ip_addr(void) { Rf_setAttrib(out, R_NamesSymbol, names); - exitlevel1: + cleanup: UNPROTECT(2); return out; From 64f0dbd164de3ad42712b4c62891ef61ac3d9328 Mon Sep 17 00:00:00 2001 From: shikokuchuo <53399081+shikokuchuo@users.noreply.github.com> Date: Sun, 4 May 2025 18:01:47 +0100 Subject: [PATCH 3/9] Optimize initialization and error paths for tls --- src/tls.c | 77 +++++++++++++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/src/tls.c b/src/tls.c index 9b50b408a..17d90e88c 100644 --- a/src/tls.c +++ b/src/tls.c @@ -115,13 +115,12 @@ SEXP rnng_write_cert(SEXP cn, SEXP valid) { const char *common = CHAR(STRING_ELT(cn, 0)); const char *not_after = CHAR(STRING_ELT(valid, 0)); /* validity period not after */ - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_pk_context key; + mbedtls_entropy_context entropy = {0}; + mbedtls_ctr_drbg_context ctr_drbg = {0}; + mbedtls_pk_context key = {0}; const char *pers = "r-nanonext-key"; - unsigned char key_buf[16000]; - memset(key_buf, 0, 16000); + unsigned char key_buf[16000] = {0}; mbedtls_entropy_init(&entropy); mbedtls_ctr_drbg_init(&ctr_drbg); @@ -138,11 +137,11 @@ SEXP rnng_write_cert(SEXP cn, SEXP valid) { char issuer_name[clen]; /* issuer name for certificate */ snprintf(issuer_name, clen, "CN=%s,O=Nanonext,C=JP", common); - int xc, exit = 1; - mbedtls_x509_crt issuer_crt; - mbedtls_pk_context loaded_issuer_key; + int xc, error = 1; + mbedtls_x509_crt issuer_crt = {0}; + mbedtls_pk_context loaded_issuer_key = {0}; mbedtls_pk_context *issuer_key = &loaded_issuer_key; - char buf[1024]; + char buf[1024] = {0}; mbedtls_x509_csr csr; // #if defined(MBEDTLS_X509_CSR_PARSE_C) mbedtls_x509write_cert crt; const char *persn = "certificate"; @@ -151,16 +150,13 @@ SEXP rnng_write_cert(SEXP cn, SEXP valid) { mbedtls_pk_init(&loaded_issuer_key); mbedtls_x509_csr_init(&csr); // #if defined(MBEDTLS_X509_CSR_PARSE_C) mbedtls_x509_crt_init(&issuer_crt); - memset(buf, 0, sizeof(buf)); - unsigned char output_buf[4096]; - memset(output_buf, 0, 4096); + unsigned char output_buf[4096] = {0}; #if MBEDTLS_VERSION_MAJOR == 3 && MBEDTLS_VERSION_MINOR >= 4 || MBEDTLS_VERSION_MAJOR >= 4 - unsigned char serial[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN]; + unsigned char serial[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN] = {0}; size_t serial_len; - memset(serial, 0, sizeof(serial)); #else - mbedtls_mpi serial; + mbedtls_mpi serial = {0}; mbedtls_mpi_init(&serial); #endif @@ -168,7 +164,7 @@ SEXP rnng_write_cert(SEXP cn, SEXP valid) { (xc = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type((mbedtls_pk_type_t) MBEDTLS_PK_RSA))) || (xc = mbedtls_rsa_gen_key(mbedtls_pk_rsa(key), mbedtls_ctr_drbg_random, &ctr_drbg, 4096, 65537)) || (xc = mbedtls_pk_write_key_pem(&key, key_buf, 16000))) - goto exitlevel1; + goto cleanup; size_t klen = strlen((char *) key_buf); @@ -183,14 +179,14 @@ SEXP rnng_write_cert(SEXP cn, SEXP valid) { #else (xc = mbedtls_pk_parse_key(&loaded_issuer_key, key_buf, klen + 1, NULL, 0))) #endif - goto exitlevel1; + goto cleanup; mbedtls_x509write_crt_set_subject_key(&crt, issuer_key); mbedtls_x509write_crt_set_issuer_key(&crt, issuer_key); if ((xc = mbedtls_x509write_crt_set_subject_name(&crt, issuer_name)) || (xc = mbedtls_x509write_crt_set_issuer_name(&crt, issuer_name))) - goto exitlevel1; + goto cleanup; mbedtls_x509write_crt_set_version(&crt, version); mbedtls_x509write_crt_set_md_alg(&crt, md); @@ -205,7 +201,7 @@ SEXP rnng_write_cert(SEXP cn, SEXP valid) { (xc = mbedtls_x509write_crt_set_subject_key_identifier(&crt)) || (xc = mbedtls_x509write_crt_set_authority_key_identifier(&crt)) || (xc = mbedtls_x509write_crt_pem(&crt, output_buf, 4096, mbedtls_ctr_drbg_random, &ctr_drbg))) - goto exitlevel1; + goto cleanup; SEXP vec, kcstr, cstr; const char *names[] = {"server", "client", ""}; @@ -219,9 +215,9 @@ SEXP rnng_write_cert(SEXP cn, SEXP valid) { SET_STRING_ELT(cstr, 0, Rf_mkChar((char *) &output_buf)); SET_STRING_ELT(cstr, 1, R_BlankString); - exit = 0; + error = 0; - exitlevel1: + cleanup: mbedtls_x509_csr_free(&csr); // #if defined(MBEDTLS_X509_CSR_PARSE_C) mbedtls_x509_crt_free(&issuer_crt); @@ -234,7 +230,7 @@ SEXP rnng_write_cert(SEXP cn, SEXP valid) { mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); - if (exit) { + if (error) { mbedtls_strerror(xc, buf, sizeof(buf)); Rf_error("%d | %s", xc, buf); } @@ -250,7 +246,7 @@ SEXP rnng_tls_config(SEXP client, SEXP server, SEXP pass, SEXP auth) { const nng_tls_auth_mode mod = NANO_INTEGER(auth) ? NNG_TLS_AUTH_MODE_REQUIRED : NNG_TLS_AUTH_MODE_OPTIONAL; R_xlen_t usefile; - nng_tls_config *cfg; + nng_tls_config *cfg = NULL; int xc; const char *crl, *file, *key, *pss; SEXP xp; @@ -258,45 +254,42 @@ SEXP rnng_tls_config(SEXP client, SEXP server, SEXP pass, SEXP auth) { if (client != R_NilValue) { file = CHAR(STRING_ELT(client, 0)); usefile = XLENGTH(client); - if ((xc = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_CLIENT))) - goto exitlevel1; - if ((xc = nng_tls_config_auth_mode(cfg, mod))) - goto exitlevel2; + if ((xc = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_CLIENT)) || + (xc = nng_tls_config_auth_mode(cfg, mod))) + goto fail; if (usefile > 1) { crl = NANO_STR_N(client, 1); if ((xc = nng_tls_config_ca_chain(cfg, file, strncmp(crl, "", 1) ? crl : NULL))) - goto exitlevel2; + goto fail; } else { file = R_ExpandFileName(file); if ((xc = nng_tls_config_ca_file(cfg, file))) - goto exitlevel2; + goto fail; } } else if (server != R_NilValue) { file = CHAR(STRING_ELT(server, 0)); usefile = XLENGTH(server); pss = pass != R_NilValue ? CHAR(STRING_ELT(pass, 0)) : NULL; - if ((xc = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_SERVER))) - goto exitlevel1; - if ((xc = nng_tls_config_auth_mode(cfg, mod))) - goto exitlevel2; + if ((xc = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_SERVER)) || + (xc = nng_tls_config_auth_mode(cfg, mod))) + goto fail; if (usefile > 1) { key = NANO_STR_N(server, 1); if ((xc = nng_tls_config_own_cert(cfg, file, key, pss))) - goto exitlevel2; + goto fail; } else { file = R_ExpandFileName(file); if ((xc = nng_tls_config_cert_key_file(cfg, file, pss))) - goto exitlevel2; + goto fail; } } else { - if ((xc = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_CLIENT))) - goto exitlevel1; - if ((xc = nng_tls_config_auth_mode(cfg, NNG_TLS_AUTH_MODE_NONE))) - goto exitlevel2; + if ((xc = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_CLIENT)) || + (xc = nng_tls_config_auth_mode(cfg, NNG_TLS_AUTH_MODE_NONE))) + goto fail; } PROTECT(xp = R_MakeExternalPtr(cfg, nano_TlsSymbol, R_NilValue)); @@ -316,9 +309,9 @@ SEXP rnng_tls_config(SEXP client, SEXP server, SEXP pass, SEXP auth) { UNPROTECT(1); return xp; - exitlevel2: - nng_tls_config_free(cfg); - exitlevel1: + fail: + if (cfg != NULL) + nng_tls_config_free(cfg); ERROR_OUT(xc); } From 28d714254a2fc472c00641c40c42b02cf7d0398b Mon Sep 17 00:00:00 2001 From: shikokuchuo <53399081+shikokuchuo@users.noreply.github.com> Date: Sun, 4 May 2025 18:10:38 +0100 Subject: [PATCH 4/9] Common error paths in sync.c --- src/sync.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/sync.c b/src/sync.c index 09bd7f64a..88face89f 100644 --- a/src/sync.c +++ b/src/sync.c @@ -204,10 +204,10 @@ SEXP rnng_cv_alloc(void) { int xc; if ((xc = nng_mtx_alloc(&cvp->mtx))) - goto exitlevel1; + goto fail; if ((xc = nng_cv_alloc(&cvp->cv, cvp->mtx))) - goto exitlevel2; + goto fail; PROTECT(xp = R_MakeExternalPtr(cvp, nano_CvSymbol, R_NilValue)); R_RegisterCFinalizerEx(xp, cv_finalizer, TRUE); @@ -216,9 +216,8 @@ SEXP rnng_cv_alloc(void) { UNPROTECT(1); return xp; - exitlevel2: + fail: nng_mtx_free(cvp->mtx); - exitlevel1: free(cvp); ERROR_OUT(xc); @@ -467,7 +466,7 @@ SEXP rnng_request(SEXP con, SEXP data, SEXP sendmode, SEXP recvmode, SEXP timeou } if ((xc = nng_ctx_open(ctx, *sock))) { free(ctx); - goto exitlevel1; + goto fail; } } else { ctx = (nng_ctx *) NANO_PTR(con); @@ -479,12 +478,12 @@ SEXP rnng_request(SEXP con, SEXP data, SEXP sendmode, SEXP recvmode, SEXP timeou saio->alloc = sock; if ((xc = nng_msg_alloc(&msg, 0))) - goto exitlevel1; + goto fail; if ((xc = nng_msg_append(msg, buf.buf, buf.cur)) || (xc = nng_aio_alloc(&saio->aio, sendaio_complete, saio))) { nng_msg_free(msg); - goto exitlevel1; + goto fail; } nng_aio_set_msg(saio->aio, msg); @@ -496,7 +495,7 @@ SEXP rnng_request(SEXP con, SEXP data, SEXP sendmode, SEXP recvmode, SEXP timeou raio->next = ncv; if ((xc = nng_aio_alloc(&raio->aio, drop ? request_complete_dropcon : request_complete, raio))) - goto exitlevel2; + goto fail; nng_aio_set_timeout(raio->aio, dur); nng_ctx_recv(*ctx, raio->aio); @@ -517,9 +516,8 @@ SEXP rnng_request(SEXP con, SEXP data, SEXP sendmode, SEXP recvmode, SEXP timeou UNPROTECT(3); return env; - exitlevel2: + fail: nng_aio_free(saio->aio); - exitlevel1: free(raio); free(saio); NANO_FREE(buf); @@ -676,10 +674,10 @@ SEXP rnng_monitor_create(SEXP socket, SEXP cv) { int xc; if ((xc = nng_pipe_notify(*sock, NNG_PIPE_EV_ADD_POST, pipe_cb_monitor, monitor))) - goto exitlevel1; + goto fail; if ((xc = nng_pipe_notify(*sock, NNG_PIPE_EV_REM_POST, pipe_cb_monitor, monitor))) - goto exitlevel1; + goto fail; PROTECT(xptr = R_MakeExternalPtr(monitor, nano_MonitorSymbol, R_NilValue)); R_RegisterCFinalizerEx(xptr, monitor_finalizer, TRUE); @@ -689,7 +687,7 @@ SEXP rnng_monitor_create(SEXP socket, SEXP cv) { return xptr; - exitlevel1: + fail: free(monitor->ids); free(monitor); ERROR_OUT(xc); From 46019b38196df30d8dd344e12792539430316b6f Mon Sep 17 00:00:00 2001 From: shikokuchuo <53399081+shikokuchuo@users.noreply.github.com> Date: Sun, 4 May 2025 18:33:02 +0100 Subject: [PATCH 5/9] Optimize paths for comms.c --- src/comms.c | 89 +++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 47 deletions(-) diff --git a/src/comms.c b/src/comms.c index cd69106a4..ea4f2cdce 100644 --- a/src/comms.c +++ b/src/comms.c @@ -100,22 +100,22 @@ SEXP rnng_dial(SEXP socket, SEXP url, SEXP tls, SEXP autostart, SEXP error) { const char *ur = CHAR(STRING_ELT(url, 0)); nng_dialer *dp = malloc(sizeof(nng_dialer)); NANO_ENSURE_ALLOC(dp); + SEXP dialer, attr, newattr, xp; - nng_tls_config *cfg; - nng_url *up; + nng_tls_config *cfg = NULL; + nng_url *up = NULL; int xc; if (sec) { - if ((xc = nng_dialer_create(dp, *sock, ur)) || - (xc = nng_url_parse(&up, ur))) - goto exitlevel1; cfg = (nng_tls_config *) NANO_PTR(tls); - if ((xc = nng_tls_config_server_name(cfg, up->u_hostname)) || + if ((xc = nng_dialer_create(dp, *sock, ur)) || + (xc = nng_url_parse(&up, ur)) || + (xc = nng_tls_config_server_name(cfg, up->u_hostname)) || (xc = nng_dialer_set_ptr(*dp, NNG_OPT_TLS_CONFIG, cfg))) - goto exitlevel2; + goto fail; nng_url_free(up); if (start && (xc = nng_dialer_start(*dp, start == 1 ? NNG_FLAG_NONBLOCK : 0))) - goto exitlevel1; + goto fail; nng_tls_config_hold(cfg); PROTECT_INDEX pxi; @@ -126,7 +126,7 @@ SEXP rnng_dial(SEXP socket, SEXP url, SEXP tls, SEXP autostart, SEXP error) { } else { if ((xc = start ? nng_dial(*sock, ur, dp, start == 1 ? NNG_FLAG_NONBLOCK : 0) : nng_dialer_create(dp, *sock, ur))) - goto exitlevel1; + goto fail; PROTECT(dialer = R_MakeExternalPtr(dp, nano_DialerSymbol, R_NilValue)); @@ -151,9 +151,8 @@ SEXP rnng_dial(SEXP socket, SEXP url, SEXP tls, SEXP autostart, SEXP error) { UNPROTECT(2); return nano_success; - exitlevel2: + fail: nng_url_free(up); - exitlevel1: free(dp); if (NANO_INTEGER(error)) ERROR_OUT(xc); ERROR_RET(xc); @@ -175,8 +174,9 @@ SEXP rnng_listen(SEXP socket, SEXP url, SEXP tls, SEXP autostart, SEXP error) { const char *ur = CHAR(STRING_ELT(url, 0)); nng_listener *lp = malloc(sizeof(nng_listener)); NANO_ENSURE_ALLOC(lp); + SEXP listener, attr, newattr, xp; - nng_tls_config *cfg; + nng_tls_config *cfg = NULL; int xc; if (sec) { @@ -184,7 +184,7 @@ SEXP rnng_listen(SEXP socket, SEXP url, SEXP tls, SEXP autostart, SEXP error) { if ((xc = nng_listener_create(lp, *sock, ur)) || (xc = nng_listener_set_ptr(*lp, NNG_OPT_TLS_CONFIG, cfg)) || (start && (xc = nng_listener_start(*lp, 0)))) - goto exitlevel1; + goto fail; nng_tls_config_hold(cfg); PROTECT_INDEX pxi; @@ -195,7 +195,7 @@ SEXP rnng_listen(SEXP socket, SEXP url, SEXP tls, SEXP autostart, SEXP error) { } else { if ((xc = start ? nng_listen(*sock, ur, lp, 0) : nng_listener_create(lp, *sock, ur))) - goto exitlevel1; + goto fail; PROTECT(listener = R_MakeExternalPtr(lp, nano_ListenerSymbol, R_NilValue)); @@ -221,7 +221,7 @@ SEXP rnng_listen(SEXP socket, SEXP url, SEXP tls, SEXP autostart, SEXP error) { UNPROTECT(2); return nano_success; - exitlevel1: + fail: free(lp); if (NANO_INTEGER(error)) ERROR_OUT(xc); ERROR_RET(xc); @@ -295,12 +295,12 @@ SEXP rnng_send(SEXP con, SEXP data, SEXP mode, SEXP block, SEXP pipe) { const int pipeid = sock ? nano_integer(pipe) : 0; nano_encodes(mode) == 2 ? nano_encode(&buf, data) : nano_serialize(&buf, data, NANO_PROT(con)); - nng_msg *msgp; + nng_msg *msgp = NULL; if (flags <= 0) { if ((xc = nng_msg_alloc(&msgp, 0))) - goto exitlevel1; + goto fail; if (pipeid) { nng_pipe p; @@ -312,17 +312,17 @@ SEXP rnng_send(SEXP con, SEXP data, SEXP mode, SEXP block, SEXP pipe) { (xc = sock ? nng_sendmsg(*(nng_socket *) NANO_PTR(con), msgp, flags ? NNG_FLAG_NONBLOCK : (NANO_INTEGER(block) != 1) * NNG_FLAG_NONBLOCK) : nng_ctx_sendmsg(*(nng_ctx *) NANO_PTR(con), msgp, flags ? NNG_FLAG_NONBLOCK : (NANO_INTEGER(block) != 1) * NNG_FLAG_NONBLOCK))) { nng_msg_free(msgp); - goto exitlevel1; + goto fail; } NANO_FREE(buf); } else { - nng_aio *aiop; + nng_aio *aiop = NULL; if ((xc = nng_msg_alloc(&msgp, 0))) - goto exitlevel1; + goto fail; if (pipeid) { nng_pipe p; @@ -333,7 +333,7 @@ SEXP rnng_send(SEXP con, SEXP data, SEXP mode, SEXP block, SEXP pipe) { if ((xc = nng_msg_append(msgp, buf.buf, buf.cur)) || (xc = nng_aio_alloc(&aiop, NULL, NULL))) { nng_msg_free(msgp); - goto exitlevel1; + goto fail; } nng_aio_set_msg(aiop, msgp); @@ -361,11 +361,11 @@ SEXP rnng_send(SEXP con, SEXP data, SEXP mode, SEXP block, SEXP pipe) { iov.iov_buf = buf.buf; if ((xc = nng_aio_alloc(&aiop, NULL, NULL))) - goto exitlevel1; + goto fail; if ((xc = nng_aio_set_iov(aiop, 1u, &iov))) { nng_aio_free(aiop); - goto exitlevel1; + goto fail; } nng_aio_set_timeout(aiop, flags ? flags : (NANO_INTEGER(block) != 0) * NNG_DURATION_DEFAULT); @@ -384,7 +384,7 @@ SEXP rnng_send(SEXP con, SEXP data, SEXP mode, SEXP block, SEXP pipe) { return nano_success; - exitlevel1: + fail: NANO_FREE(buf); return mk_error(xc); @@ -394,7 +394,7 @@ SEXP rnng_recv(SEXP con, SEXP mode, SEXP block, SEXP bytes) { const int flags = block == R_NilValue ? NNG_DURATION_DEFAULT : TYPEOF(block) == LGLSXP ? 0 : nano_integer(block); int xc; - unsigned char *buf; + unsigned char *buf = NULL; size_t sz; SEXP res; @@ -405,24 +405,23 @@ SEXP rnng_recv(SEXP con, SEXP mode, SEXP block, SEXP bytes) { if (flags <= 0) { - xc = nng_recv(*sock, &buf, &sz, NNG_FLAG_ALLOC + (flags < 0 || NANO_INTEGER(block) != 1) * NNG_FLAG_NONBLOCK); - if (xc) - goto exitlevel1; + if ((xc = nng_recv(*sock, &buf, &sz, NNG_FLAG_ALLOC + (flags < 0 || NANO_INTEGER(block) != 1) * NNG_FLAG_NONBLOCK))) + goto fail; res = nano_decode(buf, sz, mod, NANO_PROT(con)); nng_free(buf, sz); } else { - nng_aio *aiop; + nng_aio *aiop = NULL; if ((xc = nng_aio_alloc(&aiop, NULL, NULL))) - goto exitlevel1; + goto fail; nng_aio_set_timeout(aiop, flags); nng_recv_aio(*sock, aiop); nng_aio_wait(aiop); if ((xc = nng_aio_result(aiop))) { nng_aio_free(aiop); - goto exitlevel1; + goto fail; } nng_msg *msgp = nng_aio_get_msg(aiop); nng_aio_free(aiop); @@ -436,13 +435,12 @@ SEXP rnng_recv(SEXP con, SEXP mode, SEXP block, SEXP bytes) { const int mod = nano_matcharg(mode); nng_ctx *ctxp = (nng_ctx *) NANO_PTR(con); - nng_msg *msgp; + nng_msg *msgp = NULL; if (flags <= 0) { - xc = nng_ctx_recvmsg(*ctxp, &msgp, (flags < 0 || NANO_INTEGER(block) != 1) * NNG_FLAG_NONBLOCK); - if (xc) - goto exitlevel1; + if ((xc = nng_ctx_recvmsg(*ctxp, &msgp, (flags < 0 || NANO_INTEGER(block) != 1) * NNG_FLAG_NONBLOCK))) + goto fail; buf = nng_msg_body(msgp); sz = nng_msg_len(msgp); @@ -451,17 +449,17 @@ SEXP rnng_recv(SEXP con, SEXP mode, SEXP block, SEXP bytes) { } else { - nng_aio *aiop; + nng_aio *aiop = NULL; if ((xc = nng_aio_alloc(&aiop, NULL, NULL))) - goto exitlevel1; + goto fail; nng_aio_set_timeout(aiop, flags); nng_ctx_recv(*ctxp, aiop); nng_aio_wait(aiop); if ((xc = nng_aio_result(aiop))) { nng_aio_free(aiop); - goto exitlevel1; + goto fail; } msgp = nng_aio_get_msg(aiop); @@ -479,19 +477,17 @@ SEXP rnng_recv(SEXP con, SEXP mode, SEXP block, SEXP bytes) { const size_t xlen = (size_t) nano_integer(bytes); nng_stream **sp = (nng_stream **) NANO_PTR(con); nng_iov iov; - nng_aio *aiop; + nng_aio *aiop = NULL; buf = calloc(xlen, sizeof(unsigned char)); NANO_ENSURE_ALLOC(buf); iov.iov_len = xlen; iov.iov_buf = buf; - if ((xc = nng_aio_alloc(&aiop, NULL, NULL))) - goto exitlevel2; - - if ((xc = nng_aio_set_iov(aiop, 1u, &iov))) { + if ((xc = nng_aio_alloc(&aiop, NULL, NULL)) || + (xc = nng_aio_set_iov(aiop, 1u, &iov))) { nng_aio_free(aiop); - goto exitlevel2; + goto fail; } nng_aio_set_timeout(aiop, flags ? flags : (NANO_INTEGER(block) != 0) * NNG_DURATION_DEFAULT); @@ -500,7 +496,7 @@ SEXP rnng_recv(SEXP con, SEXP mode, SEXP block, SEXP bytes) { nng_aio_wait(aiop); if ((xc = nng_aio_result(aiop))) { nng_aio_free(aiop); - goto exitlevel2; + goto fail; } sz = nng_aio_count(aiop); @@ -514,9 +510,8 @@ SEXP rnng_recv(SEXP con, SEXP mode, SEXP block, SEXP bytes) { return res; - exitlevel2: + fail: free(buf); - exitlevel1: return mk_error(xc); } From 973388f9de99ae9b7af2073550bedcd33271e31b Mon Sep 17 00:00:00 2001 From: shikokuchuo <53399081+shikokuchuo@users.noreply.github.com> Date: Sun, 4 May 2025 18:42:42 +0100 Subject: [PATCH 6/9] Optimize error paths for aio.c --- src/aio.c | 46 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/src/aio.c b/src/aio.c index debd3cae7..421018dcb 100644 --- a/src/aio.c +++ b/src/aio.c @@ -510,7 +510,7 @@ SEXP rnng_send_aio(SEXP con, SEXP data, SEXP mode, SEXP timeout, SEXP pipe, SEXP const nng_duration dur = timeout == R_NilValue ? NNG_DURATION_DEFAULT : (nng_duration) nano_integer(timeout); SEXP aio, env, fun; - nano_aio *saio; + nano_aio *saio = NULL; nano_buf buf; int sock, xc; @@ -518,14 +518,18 @@ SEXP rnng_send_aio(SEXP con, SEXP data, SEXP mode, SEXP timeout, SEXP pipe, SEXP const int pipeid = sock ? nano_integer(pipe) : 0; nano_encodes(mode) == 2 ? nano_encode(&buf, data) : nano_serialize(&buf, data, NANO_PROT(con)); - nng_msg *msg; + nng_msg *msg = NULL; saio = calloc(1, sizeof(nano_aio)); NANO_ENSURE_ALLOC(saio); saio->type = SENDAIO; - if ((xc = nng_msg_alloc(&msg, 0))) - goto exitlevel1; + if ((xc = nng_msg_alloc(&msg, 0)) || + (xc = nng_msg_append(msg, buf.buf, buf.cur)) || + (xc = nng_aio_alloc(&saio->aio, saio_complete, saio))) { + nng_msg_free(msg); + goto fail; + } if (pipeid) { nng_pipe p; @@ -533,12 +537,6 @@ SEXP rnng_send_aio(SEXP con, SEXP data, SEXP mode, SEXP timeout, SEXP pipe, SEXP nng_msg_set_pipe(msg, p); } - if ((xc = nng_msg_append(msg, buf.buf, buf.cur)) || - (xc = nng_aio_alloc(&saio->aio, saio_complete, saio))) { - nng_msg_free(msg); - goto exitlevel1; - } - nng_aio_set_msg(saio->aio, msg); nng_aio_set_timeout(saio->aio, dur); sock ? nng_send_aio(*(nng_socket *) NANO_PTR(con), saio->aio) : @@ -565,11 +563,9 @@ SEXP rnng_send_aio(SEXP con, SEXP data, SEXP mode, SEXP timeout, SEXP pipe, SEXP iov.iov_len = buf.cur - nst->textframes; iov.iov_buf = saio->data; - if ((xc = nng_aio_alloc(&saio->aio, isaio_complete, saio))) - goto exitlevel2; - - if ((xc = nng_aio_set_iov(saio->aio, 1u, &iov))) - goto exitlevel3; + if ((xc = nng_aio_alloc(&saio->aio, isaio_complete, saio)) || + (xc = nng_aio_set_iov(saio->aio, 1u, &iov))) + goto fail; nng_aio_set_timeout(saio->aio, dur); nng_stream_send(sp, saio->aio); @@ -594,11 +590,9 @@ SEXP rnng_send_aio(SEXP con, SEXP data, SEXP mode, SEXP timeout, SEXP pipe, SEXP UNPROTECT(3); return env; - exitlevel3: + fail: nng_aio_free(saio->aio); - exitlevel2: free(saio->data); - exitlevel1: NANO_FREE(buf); free(saio); return mk_error_data(-xc); @@ -617,7 +611,7 @@ SEXP rnng_recv_aio(SEXP con, SEXP mode, SEXP timeout, SEXP cvar, SEXP bytes, SEX interrupt = 1 - signal; } nano_cv *ncv = signal ? (nano_cv *) NANO_PTR(cvar) : NULL; - nano_aio *raio; + nano_aio *raio = NULL; SEXP aio, env, fun; int sock, xc; @@ -631,7 +625,7 @@ SEXP rnng_recv_aio(SEXP con, SEXP mode, SEXP timeout, SEXP cvar, SEXP bytes, SEX raio->mode = mod; if ((xc = nng_aio_alloc(&raio->aio, interrupt ? raio_complete_interrupt : raio_complete, raio))) - goto exitlevel1; + goto fail; nng_aio_set_timeout(raio->aio, dur); sock ? nng_recv_aio(*(nng_socket *) NANO_PTR(con), raio->aio) : @@ -657,11 +651,9 @@ SEXP rnng_recv_aio(SEXP con, SEXP mode, SEXP timeout, SEXP cvar, SEXP bytes, SEX iov.iov_len = xlen; iov.iov_buf = raio->data; - if ((xc = nng_aio_alloc(&raio->aio, iraio_complete, raio))) - goto exitlevel2; - - if ((xc = nng_aio_set_iov(raio->aio, 1u, &iov))) - goto exitlevel3; + if ((xc = nng_aio_alloc(&raio->aio, iraio_complete, raio)) || + (xc = nng_aio_set_iov(raio->aio, 1u, &iov))) + goto fail; nng_aio_set_timeout(raio->aio, dur); nng_stream_recv(*sp, raio->aio); @@ -683,11 +675,9 @@ SEXP rnng_recv_aio(SEXP con, SEXP mode, SEXP timeout, SEXP cvar, SEXP bytes, SEX UNPROTECT(3); return env; - exitlevel3: + fail: nng_aio_free(raio->aio); - exitlevel2: free(raio->data); - exitlevel1: free(raio); return mk_error_data(xc); From 066ac59e303699040b3fbc3cf804c635f5151d30 Mon Sep 17 00:00:00 2001 From: shikokuchuo <53399081+shikokuchuo@users.noreply.github.com> Date: Sun, 4 May 2025 19:30:50 +0100 Subject: [PATCH 7/9] Optimize error paths for ncurl --- src/ncurl.c | 193 ++++++++++++++++++++++------------------------------ 1 file changed, 82 insertions(+), 111 deletions(-) diff --git a/src/ncurl.c b/src/ncurl.c index 9849447fd..3313cf446 100644 --- a/src/ncurl.c +++ b/src/ncurl.c @@ -142,68 +142,61 @@ SEXP rnng_ncurl(SEXP http, SEXP convert, SEXP follow, SEXP method, SEXP headers, Rf_error("'tls' is not a valid TLS Configuration"); int chk_resp = response != R_NilValue && TYPEOF(response) == STRSXP; - nng_url *url; - nng_http_client *client; - nng_http_req *req; - nng_http_res *res; - nng_aio *aio; + nng_url *url = NULL; + nng_http_client *client = NULL; + nng_http_req *req = NULL; + nng_http_res *res = NULL; + nng_aio *aio = NULL; nng_tls_config *cfg = NULL; uint16_t code, relo; int xc; if ((xc = nng_url_parse(&url, addr))) - goto exitlevel1; + goto fail; relocall: - if ((xc = nng_http_client_alloc(&client, url))) - goto exitlevel2; - if ((xc = nng_http_req_alloc(&req, url))) - goto exitlevel3; + if ((xc = nng_http_client_alloc(&client, url)) || + (xc = nng_http_req_alloc(&req, url)) || + (xc = nng_http_res_alloc(&res)) || + (xc = nng_aio_alloc(&aio, NULL, NULL))) + goto fail; + if (mthd != NULL && (xc = nng_http_req_set_method(req, mthd))) - goto exitlevel4; + goto fail; + if (headers != R_NilValue && TYPEOF(headers) == STRSXP) { const R_xlen_t hlen = XLENGTH(headers); SEXP hnames = Rf_getAttrib(headers, R_NamesSymbol); if (TYPEOF(hnames) == STRSXP && XLENGTH(hnames) == hlen) { for (R_xlen_t i = 0; i < hlen; i++) { - if ((xc = nng_http_req_set_header(req, - NANO_STR_N(hnames, i), - NANO_STR_N(headers, i)))) - goto exitlevel4; + if ((xc = nng_http_req_set_header(req, NANO_STR_N(hnames, i), NANO_STR_N(headers, i)))) + goto fail; } } } if (data != R_NilValue && TYPEOF(data) == STRSXP) { nano_buf enc = nano_char_buf(data); if ((xc = nng_http_req_set_data(req, enc.buf, enc.cur))) - goto exitlevel4; + goto fail; } - if ((xc = nng_http_res_alloc(&res))) - goto exitlevel4; - - if ((xc = nng_aio_alloc(&aio, NULL, NULL))) - goto exitlevel5; - if (!strcmp(url->u_scheme, "https")) { if (tls == R_NilValue) { - if ((xc = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_CLIENT))) - goto exitlevel6; - - if ((xc = nng_tls_config_server_name(cfg, url->u_hostname)) || + if ((xc = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_CLIENT)) || + (xc = nng_tls_config_server_name(cfg, url->u_hostname)) || (xc = nng_tls_config_auth_mode(cfg, NNG_TLS_AUTH_MODE_NONE)) || (xc = nng_http_client_set_tls(client, cfg))) - goto exitlevel7; - } else { + goto fail; + } else { cfg = (nng_tls_config *) NANO_PTR(tls); nng_tls_config_hold(cfg); if ((xc = nng_tls_config_server_name(cfg, url->u_hostname)) || (xc = nng_http_client_set_tls(client, cfg))) - goto exitlevel7; + goto fail; } } @@ -212,7 +205,7 @@ SEXP rnng_ncurl(SEXP http, SEXP convert, SEXP follow, SEXP method, SEXP headers, nng_http_client_transact(client, req, res, aio); nng_aio_wait(aio); if ((xc = nng_aio_result(aio))) - goto exitlevel7; + goto fail; if (cfg != NULL) nng_tls_config_free(cfg); @@ -227,8 +220,11 @@ SEXP rnng_ncurl(SEXP http, SEXP convert, SEXP follow, SEXP method, SEXP headers, xc = nng_url_parse(&url, location); if (xc) goto resume; nng_http_res_free(res); + res = NULL; nng_http_req_free(req); + req = NULL; nng_http_client_free(client); + client = NULL; nng_url_free(oldurl); cfg = NULL; goto relocall; @@ -290,20 +286,17 @@ SEXP rnng_ncurl(SEXP http, SEXP convert, SEXP follow, SEXP method, SEXP headers, UNPROTECT(1); return out; - exitlevel7: + fail: if (cfg != NULL) nng_tls_config_free(cfg); - exitlevel6: nng_aio_free(aio); - exitlevel5: - nng_http_res_free(res); - exitlevel4: - nng_http_req_free(req); - exitlevel3: - nng_http_client_free(client); - exitlevel2: + if (res != NULL) + nng_http_res_free(res); + if (req != NULL) + nng_http_req_free(req); + if (client != NULL) + nng_http_client_free(client); nng_url_free(url); - exitlevel1: return mk_error_ncurl(xc); } @@ -329,57 +322,48 @@ SEXP rnng_ncurl_aio(SEXP http, SEXP convert, SEXP method, SEXP headers, SEXP dat haio->mode = (uint8_t) NANO_INTEGER(convert); haio->next = handle; - if ((xc = nng_url_parse(&handle->url, httr))) - goto exitlevel1; - if ((xc = nng_http_client_alloc(&handle->cli, handle->url))) - goto exitlevel2; - if ((xc = nng_http_req_alloc(&handle->req, handle->url))) - goto exitlevel3; + if ((xc = nng_url_parse(&handle->url, httr)) || + (xc = nng_http_client_alloc(&handle->cli, handle->url)) || + (xc = nng_http_req_alloc(&handle->req, handle->url)) || + (xc = nng_http_res_alloc(&handle->res)) || + (xc = nng_aio_alloc(&haio->aio, haio_complete, haio))) + goto fail; + if (mthd != NULL && (xc = nng_http_req_set_method(handle->req, mthd))) - goto exitlevel4; + goto fail; + if (headers != R_NilValue && TYPEOF(headers) == STRSXP) { const R_xlen_t hlen = XLENGTH(headers); SEXP hnames = Rf_getAttrib(headers, R_NamesSymbol); if (TYPEOF(hnames) == STRSXP && XLENGTH(hnames) == hlen) { for (R_xlen_t i = 0; i < hlen; i++) { - if ((xc = nng_http_req_set_header(handle->req, - NANO_STR_N(hnames, i), - NANO_STR_N(headers, i)))) - goto exitlevel4; + if ((xc = nng_http_req_set_header(handle->req, NANO_STR_N(hnames, i), NANO_STR_N(headers, i)))) + goto fail; } } } if (data != R_NilValue && TYPEOF(data) == STRSXP) { nano_buf enc = nano_char_buf(data); if ((xc = nng_http_req_set_data(handle->req, enc.buf, enc.cur))) - goto exitlevel4; + goto fail; } - if ((xc = nng_http_res_alloc(&handle->res))) - goto exitlevel4; - - if ((xc = nng_aio_alloc(&haio->aio, haio_complete, haio))) - goto exitlevel5; - if (!strcmp(handle->url->u_scheme, "https")) { if (tls == R_NilValue) { - if ((xc = nng_tls_config_alloc(&handle->cfg, NNG_TLS_MODE_CLIENT))) - goto exitlevel6; - - if ((xc = nng_tls_config_server_name(handle->cfg, handle->url->u_hostname)) || + if ((xc = nng_tls_config_alloc(&handle->cfg, NNG_TLS_MODE_CLIENT)) || + (xc = nng_tls_config_server_name(handle->cfg, handle->url->u_hostname)) || (xc = nng_tls_config_auth_mode(handle->cfg, NNG_TLS_AUTH_MODE_NONE)) || (xc = nng_http_client_set_tls(handle->cli, handle->cfg))) - goto exitlevel7; + goto fail; } else { - handle->cfg = (nng_tls_config *) NANO_PTR(tls); nng_tls_config_hold(handle->cfg); if ((xc = nng_tls_config_server_name(handle->cfg, handle->url->u_hostname)) || (xc = nng_http_client_set_tls(handle->cli, handle->cfg))) - goto exitlevel7; + goto fail; } } @@ -409,19 +393,17 @@ SEXP rnng_ncurl_aio(SEXP http, SEXP convert, SEXP method, SEXP headers, SEXP dat UNPROTECT(2); return env; - exitlevel7: - nng_tls_config_free(handle->cfg); - exitlevel6: + fail: + if (handle->cfg != NULL) + nng_tls_config_free(handle->cfg); nng_aio_free(haio->aio); - exitlevel5: - nng_http_res_free(handle->res); - exitlevel4: - nng_http_req_free(handle->req); - exitlevel3: - nng_http_client_free(handle->cli); - exitlevel2: + if (handle->res != NULL) + nng_http_res_free(handle->res); + if (handle->req != NULL) + nng_http_req_free(handle->req); + if (handle->cli != NULL) + nng_http_client_free(handle->cli); nng_url_free(handle->url); - exitlevel1: free(handle); free(haio); return mk_error_ncurlaio(xc); @@ -542,48 +524,40 @@ SEXP rnng_ncurl_session(SEXP http, SEXP convert, SEXP method, SEXP headers, SEXP haio->mode = (uint8_t) NANO_INTEGER(convert); haio->next = handle; - if ((xc = nng_url_parse(&handle->url, httr))) - goto exitlevel1; - if ((xc = nng_http_client_alloc(&handle->cli, handle->url))) - goto exitlevel2; - if ((xc = nng_http_req_alloc(&handle->req, handle->url))) - goto exitlevel3; + if ((xc = nng_url_parse(&handle->url, httr)) || + (xc = nng_http_client_alloc(&handle->cli, handle->url)) || + (xc = nng_http_req_alloc(&handle->req, handle->url)) || + (xc = nng_http_res_alloc(&handle->res)) || + (xc = nng_aio_alloc(&haio->aio, session_complete, haio))) + goto fail; + if (mthd != NULL && (xc = nng_http_req_set_method(handle->req, mthd))) - goto exitlevel4; + goto fail; + if (headers != R_NilValue && TYPEOF(headers) == STRSXP) { const R_xlen_t hlen = XLENGTH(headers); SEXP hnames = Rf_getAttrib(headers, R_NamesSymbol); if (TYPEOF(hnames) == STRSXP && XLENGTH(hnames) == hlen) { for (R_xlen_t i = 0; i < hlen; i++) { - if ((xc = nng_http_req_set_header(handle->req, - NANO_STR_N(hnames, i), - NANO_STR_N(headers, i)))) - goto exitlevel4; + if ((xc = nng_http_req_set_header(handle->req, NANO_STR_N(hnames, i), NANO_STR_N(headers, i)))) + goto fail; } } } if (data != R_NilValue && TYPEOF(data) == STRSXP) { nano_buf enc = nano_char_buf(data); if ((xc = nng_http_req_set_data(handle->req, enc.buf, enc.cur))) - goto exitlevel4; + goto fail; } - if ((xc = nng_http_res_alloc(&handle->res))) - goto exitlevel4; - - if ((xc = nng_aio_alloc(&haio->aio, session_complete, haio))) - goto exitlevel5; - if (!strcmp(handle->url->u_scheme, "https")) { if (tls == R_NilValue) { - if ((xc = nng_tls_config_alloc(&handle->cfg, NNG_TLS_MODE_CLIENT))) - goto exitlevel6; - - if ((xc = nng_tls_config_server_name(handle->cfg, handle->url->u_hostname)) || + if ((xc = nng_tls_config_alloc(&handle->cfg, NNG_TLS_MODE_CLIENT)) || + (xc = nng_tls_config_server_name(handle->cfg, handle->url->u_hostname)) || (xc = nng_tls_config_auth_mode(handle->cfg, NNG_TLS_AUTH_MODE_NONE)) || (xc = nng_http_client_set_tls(handle->cli, handle->cfg))) - goto exitlevel7; + goto fail; } else { @@ -592,7 +566,7 @@ SEXP rnng_ncurl_session(SEXP http, SEXP convert, SEXP method, SEXP headers, SEXP if ((xc = nng_tls_config_server_name(handle->cfg, handle->url->u_hostname)) || (xc = nng_http_client_set_tls(handle->cli, handle->cfg))) - goto exitlevel7; + goto fail; } } @@ -601,7 +575,7 @@ SEXP rnng_ncurl_session(SEXP http, SEXP convert, SEXP method, SEXP headers, SEXP nng_http_client_connect(handle->cli, haio->aio); nng_aio_wait(haio->aio); if ((xc = haio->result) > 0) - goto exitlevel7; + goto fail; nng_http_conn *conn = nng_aio_get_output(haio->aio, 0); haio->data = conn; @@ -613,20 +587,17 @@ SEXP rnng_ncurl_session(SEXP http, SEXP convert, SEXP method, SEXP headers, SEXP UNPROTECT(1); return sess; - exitlevel7: + fail: if (handle->cfg != NULL) nng_tls_config_free(handle->cfg); - exitlevel6: nng_aio_free(haio->aio); - exitlevel5: - nng_http_res_free(handle->res); - exitlevel4: - nng_http_req_free(handle->req); - exitlevel3: - nng_http_client_free(handle->cli); - exitlevel2: + if (handle->res != NULL) + nng_http_res_free(handle->res); + if (handle->req != NULL) + nng_http_req_free(handle->req); + if (handle->cli != NULL) + nng_http_client_free(handle->cli); nng_url_free(handle->url); - exitlevel1: free(handle); free(haio); ERROR_RET(xc); From 85615e9ec73027332648fa1f4932cbea3c45cc96 Mon Sep 17 00:00:00 2001 From: shikokuchuo <53399081+shikokuchuo@users.noreply.github.com> Date: Sun, 4 May 2025 19:48:21 +0100 Subject: [PATCH 8/9] Optimize threaded function error paths --- src/thread.c | 57 +++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/src/thread.c b/src/thread.c index 09e0d3d1e..da428ef70 100644 --- a/src/thread.c +++ b/src/thread.c @@ -142,20 +142,22 @@ SEXP rnng_messenger(SEXP url) { SEXP socket, con; if ((xc = nng_pair0_open(sock))) - goto exitlevel1; + goto fail; lp = malloc(sizeof(nng_listener)); - NANO_ENSURE_ALLOC_FREE(lp, sock); + if (lp == NULL) + goto failmem; if ((xc = nng_listen(*sock, up, lp, 0))) { if (xc != 10 && xc != 15) { free(lp); - goto exitlevel2; + goto failclose; } free(lp); dp = malloc(sizeof(nng_dialer)); - NANO_ENSURE_ALLOC_FREE(dp, sock); + if (dp == NULL) + goto failmem; if ((xc = nng_dial(*sock, up, dp, 0))) { free(dp); - goto exitlevel2; + goto failclose; } dialer = 1; } @@ -174,12 +176,17 @@ SEXP rnng_messenger(SEXP url) { UNPROTECT(2); return socket; - exitlevel2: + failclose: nng_close(*sock); - exitlevel1: + fail: free(sock); ERROR_OUT(xc); + failmem: + nng_close(*sock); + free(sock); + Rf_error("Memory allocation failed"); + } SEXP rnng_messenger_thread_create(SEXP args) { @@ -240,21 +247,19 @@ void single_wait_thread_create(SEXP x) { NANO_ENSURE_ALLOC_FREE(ncv, taio); taio->aio = aiop->aio; taio->cv = ncv; - nng_mtx *mtx; - nng_cv *cv; + nng_mtx *mtx = NULL; + nng_cv *cv = NULL; int xc, signalled; - if ((xc = nng_mtx_alloc(&mtx))) - goto exitlevel1; - - if ((xc = nng_cv_alloc(&cv, mtx))) - goto exitlevel2; + if ((xc = nng_mtx_alloc(&mtx)) || + (xc = nng_cv_alloc(&cv, mtx))) + goto fail; ncv->mtx = mtx; ncv->cv = cv; if ((xc = nng_thread_create(&taio->thr, rnng_wait_thread_single, taio))) - goto exitlevel3; + goto fail; SEXP xptr; PROTECT(xptr = R_MakeExternalPtr(taio, R_NilValue, R_NilValue)); @@ -281,11 +286,9 @@ void single_wait_thread_create(SEXP x) { return; - exitlevel3: + fail: nng_cv_free(cv); - exitlevel2: nng_mtx_free(mtx); - exitlevel1: free(ncv); free(taio); ERROR_OUT(xc); @@ -348,15 +351,11 @@ SEXP rnng_wait_thread_create(SEXP x) { int xc, signalled; - if (!nano_wait_thr) { - if ((xc = nng_mtx_alloc(&nano_wait_mtx))) - goto exitlevel1; - - if ((xc = nng_cv_alloc(&nano_wait_cv, nano_wait_mtx))) - goto exitlevel2; - - if ((xc = nng_thread_create(&nano_wait_thr, rnng_wait_thread, NULL))) - goto exitlevel3; + if (nano_wait_thr == NULL) { + if ((xc = nng_mtx_alloc(&nano_wait_mtx)) || + (xc = nng_cv_alloc(&nano_wait_cv, nano_wait_mtx)) || + (xc = nng_thread_create(&nano_wait_thr, rnng_wait_thread, NULL))) + goto fail; } int thread_required = 0; @@ -417,11 +416,9 @@ SEXP rnng_wait_thread_create(SEXP x) { return x; - exitlevel3: + fail: nng_cv_free(nano_wait_cv); - exitlevel2: nng_mtx_free(nano_wait_mtx); - exitlevel1: ERROR_OUT(xc); } else if (typ == VECSXP) { From e8d64668b884c5e9834fc870341e45fb9ae4e42f Mon Sep 17 00:00:00 2001 From: shikokuchuo <53399081+shikokuchuo@users.noreply.github.com> Date: Sun, 4 May 2025 21:35:45 +0100 Subject: [PATCH 9/9] Integrate memory allocation errors with nng error system --- src/aio.c | 18 ++++++++---- src/comms.c | 50 +++++++++++++++++++++------------ src/core.c | 5 +--- src/nanonext.h | 3 +- src/ncurl.c | 25 +++++++++++------ src/net.c | 3 +- src/proto.c | 33 ++++++++++++++-------- src/sync.c | 75 +++++++++++++++++++++++++++----------------------- src/thread.c | 71 ++++++++++++++++++++++++----------------------- 9 files changed, 164 insertions(+), 119 deletions(-) diff --git a/src/aio.c b/src/aio.c index 421018dcb..1d70fdfec 100644 --- a/src/aio.c +++ b/src/aio.c @@ -508,7 +508,7 @@ SEXP rnng_unresolved2(SEXP x) { SEXP rnng_send_aio(SEXP con, SEXP data, SEXP mode, SEXP timeout, SEXP pipe, SEXP clo) { const nng_duration dur = timeout == R_NilValue ? NNG_DURATION_DEFAULT : (nng_duration) nano_integer(timeout); - + const int raw = nano_encodes(mode) == 2; SEXP aio, env, fun; nano_aio *saio = NULL; nano_buf buf; @@ -517,11 +517,15 @@ SEXP rnng_send_aio(SEXP con, SEXP data, SEXP mode, SEXP timeout, SEXP pipe, SEXP if ((sock = !NANO_PTR_CHECK(con, nano_SocketSymbol)) || !NANO_PTR_CHECK(con, nano_ContextSymbol)) { const int pipeid = sock ? nano_integer(pipe) : 0; - nano_encodes(mode) == 2 ? nano_encode(&buf, data) : nano_serialize(&buf, data, NANO_PROT(con)); + if (raw) { + nano_encode(&buf, data); + } else { + nano_serialize(&buf, data, NANO_PROT(con)); + } nng_msg *msg = NULL; saio = calloc(1, sizeof(nano_aio)); - NANO_ENSURE_ALLOC(saio); + if (saio == NULL) { xc = 2; goto failmem; } saio->type = SENDAIO; if ((xc = nng_msg_alloc(&msg, 0)) || @@ -555,10 +559,10 @@ SEXP rnng_send_aio(SEXP con, SEXP data, SEXP mode, SEXP timeout, SEXP pipe, SEXP nng_iov iov; saio = calloc(1, sizeof(nano_aio)); - NANO_ENSURE_ALLOC(saio); + if (saio == NULL) { xc = 2; goto failmem; } saio->type = IOV_SENDAIO; saio->data = calloc(buf.cur, sizeof(unsigned char)); - NANO_ENSURE_ALLOC_FREE(saio->data, saio); + if (saio->data == NULL) { xc = 2; goto failmem; } memcpy(saio->data, buf.buf, buf.cur); iov.iov_len = buf.cur - nst->textframes; iov.iov_buf = saio->data; @@ -593,6 +597,7 @@ SEXP rnng_send_aio(SEXP con, SEXP data, SEXP mode, SEXP timeout, SEXP pipe, SEXP fail: nng_aio_free(saio->aio); free(saio->data); + failmem: NANO_FREE(buf); free(saio); return mk_error_data(-xc); @@ -647,7 +652,7 @@ SEXP rnng_recv_aio(SEXP con, SEXP mode, SEXP timeout, SEXP cvar, SEXP bytes, SEX raio->type = signal ? IOV_RECVAIOS : IOV_RECVAIO; raio->mode = mod; raio->data = calloc(xlen, sizeof(unsigned char)); - NANO_ENSURE_ALLOC_FREE(raio->data, raio); + NANO_ENSURE_ALLOC(raio->data); iov.iov_len = xlen; iov.iov_buf = raio->data; @@ -678,6 +683,7 @@ SEXP rnng_recv_aio(SEXP con, SEXP mode, SEXP timeout, SEXP cvar, SEXP bytes, SEX fail: nng_aio_free(raio->aio); free(raio->data); + failmem: free(raio); return mk_error_data(xc); diff --git a/src/comms.c b/src/comms.c index ea4f2cdce..f4643c70e 100644 --- a/src/comms.c +++ b/src/comms.c @@ -21,15 +21,13 @@ SEXP rnng_ctx_open(SEXP socket) { Rf_error("'socket' is not a valid Socket"); nng_socket *sock = (nng_socket *) NANO_PTR(socket); + SEXP context; + int xc; nng_ctx *ctx = malloc(sizeof(nng_ctx)); NANO_ENSURE_ALLOC(ctx); - SEXP context; - const int xc = nng_ctx_open(ctx, *sock); - if (xc) { - free(ctx); - ERROR_OUT(xc); - } + if ((xc = nng_ctx_open(ctx, *sock))) + goto fail; PROTECT(context = R_MakeExternalPtr(ctx, nano_ContextSymbol, NANO_PROT(socket))); R_RegisterCFinalizerEx(context, context_finalizer, TRUE); @@ -43,6 +41,11 @@ SEXP rnng_ctx_open(SEXP socket) { UNPROTECT(1); return context; + fail: + free(ctx); + failmem: + ERROR_OUT(xc); + } SEXP rnng_ctx_create(SEXP socket) { @@ -51,21 +54,24 @@ SEXP rnng_ctx_create(SEXP socket) { Rf_error("'socket' is not a valid Socket"); nng_socket *sock = (nng_socket *) NANO_PTR(socket); + SEXP context; + int xc; nng_ctx *ctx = malloc(sizeof(nng_ctx)); NANO_ENSURE_ALLOC(ctx); - SEXP context; - const int xc = nng_ctx_open(ctx, *sock); - if (xc) { - free(ctx); - ERROR_OUT(xc); - } + if ((xc = nng_ctx_open(ctx, *sock))) + goto fail; PROTECT(context = R_MakeExternalPtr(ctx, nano_ContextSymbol, NANO_PROT(socket))); R_RegisterCFinalizerEx(context, context_finalizer, TRUE); UNPROTECT(1); return context; + fail: + free(ctx); + failmem: + ERROR_OUT(xc); + } SEXP rnng_ctx_close(SEXP context) { @@ -98,14 +104,15 @@ SEXP rnng_dial(SEXP socket, SEXP url, SEXP tls, SEXP autostart, SEXP error) { nng_socket *sock = (nng_socket *) NANO_PTR(socket); const int start = NANO_INTEGER(autostart); const char *ur = CHAR(STRING_ELT(url, 0)); - nng_dialer *dp = malloc(sizeof(nng_dialer)); - NANO_ENSURE_ALLOC(dp); SEXP dialer, attr, newattr, xp; nng_tls_config *cfg = NULL; nng_url *up = NULL; int xc; + nng_dialer *dp = malloc(sizeof(nng_dialer)); + NANO_ENSURE_ALLOC(dp); + if (sec) { cfg = (nng_tls_config *) NANO_PTR(tls); if ((xc = nng_dialer_create(dp, *sock, ur)) || @@ -154,6 +161,7 @@ SEXP rnng_dial(SEXP socket, SEXP url, SEXP tls, SEXP autostart, SEXP error) { fail: nng_url_free(up); free(dp); + failmem: if (NANO_INTEGER(error)) ERROR_OUT(xc); ERROR_RET(xc); @@ -172,13 +180,14 @@ SEXP rnng_listen(SEXP socket, SEXP url, SEXP tls, SEXP autostart, SEXP error) { nng_socket *sock = (nng_socket *) NANO_PTR(socket); const int start = NANO_INTEGER(autostart); const char *ur = CHAR(STRING_ELT(url, 0)); - nng_listener *lp = malloc(sizeof(nng_listener)); - NANO_ENSURE_ALLOC(lp); SEXP listener, attr, newattr, xp; nng_tls_config *cfg = NULL; int xc; + nng_listener *lp = malloc(sizeof(nng_listener)); + NANO_ENSURE_ALLOC(lp); + if (sec) { cfg = (nng_tls_config *) NANO_PTR(tls); if ((xc = nng_listener_create(lp, *sock, ur)) || @@ -223,6 +232,7 @@ SEXP rnng_listen(SEXP socket, SEXP url, SEXP tls, SEXP autostart, SEXP error) { fail: free(lp); + failmem: if (NANO_INTEGER(error)) ERROR_OUT(xc); ERROR_RET(xc); @@ -288,13 +298,18 @@ SEXP rnng_listener_close(SEXP listener) { SEXP rnng_send(SEXP con, SEXP data, SEXP mode, SEXP block, SEXP pipe) { const int flags = block == R_NilValue ? NNG_DURATION_DEFAULT : TYPEOF(block) == LGLSXP ? 0 : nano_integer(block); + const int raw = nano_encodes(mode) == 2; nano_buf buf; int sock, xc; if ((sock = !NANO_PTR_CHECK(con, nano_SocketSymbol)) || !NANO_PTR_CHECK(con, nano_ContextSymbol)) { const int pipeid = sock ? nano_integer(pipe) : 0; - nano_encodes(mode) == 2 ? nano_encode(&buf, data) : nano_serialize(&buf, data, NANO_PROT(con)); + if (raw) { + nano_encode(&buf, data); + } else { + nano_serialize(&buf, data, NANO_PROT(con)); + } nng_msg *msgp = NULL; if (flags <= 0) { @@ -512,6 +527,7 @@ SEXP rnng_recv(SEXP con, SEXP mode, SEXP block, SEXP bytes) { fail: free(buf); + failmem: return mk_error(xc); } diff --git a/src/core.c b/src/core.c index bc5ea5bbb..120b83c25 100644 --- a/src/core.c +++ b/src/core.c @@ -370,10 +370,7 @@ SEXP nano_unserialize(unsigned char *buf, size_t sz, SEXP hook) { return nano_decode(buf, sz, 8, R_NilValue); } - nano_buf nbuf; - nbuf.buf = buf; - nbuf.len = sz; - nbuf.cur = cur; + nano_buf nbuf = {.buf = buf, .len = sz, .cur = cur}; struct R_inpstream_st input_stream; diff --git a/src/nanonext.h b/src/nanonext.h index 1217b8435..d06d7cca0 100644 --- a/src/nanonext.h +++ b/src/nanonext.h @@ -140,8 +140,7 @@ extern int R_interrupts_pending; Rf_classgets(x, klass); \ SET_STRING_ELT(klass, 0, Rf_mkChar(cls1)); \ SET_STRING_ELT(klass, 1, Rf_mkChar(cls2)) -#define NANO_ENSURE_ALLOC(x) if (x == NULL) Rf_error("Memory allocation failed") -#define NANO_ENSURE_ALLOC_FREE(x, y) if (x == NULL) { free(y); Rf_error("Memory allocation failed"); } +#define NANO_ENSURE_ALLOC(x) if (x == NULL) { xc = 2; goto failmem; } typedef union nano_opt_u { char *str; diff --git a/src/ncurl.c b/src/ncurl.c index 3313cf446..5ab22b992 100644 --- a/src/ncurl.c +++ b/src/ncurl.c @@ -311,12 +311,15 @@ SEXP rnng_ncurl_aio(SEXP http, SEXP convert, SEXP method, SEXP headers, SEXP dat const nng_duration dur = timeout == R_NilValue ? NNG_DURATION_DEFAULT : (nng_duration) nano_integer(timeout); if (tls != R_NilValue && NANO_PTR_CHECK(tls, nano_TlsSymbol)) Rf_error("'tls' is not a valid TLS Configuration"); - nano_aio *haio = calloc(1, sizeof(nano_aio)); - NANO_ENSURE_ALLOC(haio); - nano_handle *handle = calloc(1, sizeof(nano_handle)); - NANO_ENSURE_ALLOC_FREE(handle, haio); + SEXP aio, env, fun; int xc; + nano_aio *haio = NULL; + nano_handle *handle = NULL; + haio = calloc(1, sizeof(nano_aio)); + NANO_ENSURE_ALLOC(haio); + handle = calloc(1, sizeof(nano_handle)); + NANO_ENSURE_ALLOC(handle); haio->type = HTTP_AIO; haio->mode = (uint8_t) NANO_INTEGER(convert); @@ -404,6 +407,7 @@ SEXP rnng_ncurl_aio(SEXP http, SEXP convert, SEXP method, SEXP headers, SEXP dat if (handle->cli != NULL) nng_http_client_free(handle->cli); nng_url_free(handle->url); + failmem: free(handle); free(haio); return mk_error_ncurlaio(xc); @@ -513,12 +517,14 @@ SEXP rnng_ncurl_session(SEXP http, SEXP convert, SEXP method, SEXP headers, SEXP if (tls != R_NilValue && NANO_PTR_CHECK(tls, nano_TlsSymbol)) Rf_error("'tls' is not a valid TLS Configuration"); - nano_aio *haio = calloc(1, sizeof(nano_aio)); - NANO_ENSURE_ALLOC(haio); - nano_handle *handle = calloc(1, sizeof(nano_handle)); - NANO_ENSURE_ALLOC_FREE(handle, haio); - int xc; SEXP sess; + int xc; + nano_aio *haio = NULL; + nano_handle *handle = NULL; + haio = calloc(1, sizeof(nano_aio)); + NANO_ENSURE_ALLOC(haio); + handle = calloc(1, sizeof(nano_handle)); + NANO_ENSURE_ALLOC(handle); haio->type = HTTP_AIO; haio->mode = (uint8_t) NANO_INTEGER(convert); @@ -598,6 +604,7 @@ SEXP rnng_ncurl_session(SEXP http, SEXP convert, SEXP method, SEXP headers, SEXP if (handle->cli != NULL) nng_http_client_free(handle->cli); nng_url_free(handle->url); + failmem: free(handle); free(haio); ERROR_RET(xc); diff --git a/src/net.c b/src/net.c index 498f72ce8..e95386879 100644 --- a/src/net.c +++ b/src/net.c @@ -25,7 +25,8 @@ SEXP rnng_ip_addr(void) { int j = 0; do { addrs = malloc(bufsize); - NANO_ENSURE_ALLOC(addrs); + if (addrs == NULL) + goto cleanup; ret = GetAdaptersAddresses(AF_INET, flags, NULL, addrs, &bufsize); if (ret == ERROR_BUFFER_OVERFLOW) diff --git a/src/proto.c b/src/proto.c index 42c647cda..8dba75db0 100644 --- a/src/proto.c +++ b/src/proto.c @@ -116,10 +116,8 @@ SEXP rnng_protocol_open(SEXP protocol, SEXP dial, SEXP listen, SEXP tls, SEXP au NANO_ERROR("'protocol' should be one of bus, pair, poly, push, pull, pub, sub, req, rep, surveyor, respondent"); } - if (xc) { - free(sock); - ERROR_OUT(xc); - } + if (xc) + goto fail; PROTECT(socket = R_MakeExternalPtr(sock, nano_SocketSymbol, R_NilValue)); R_RegisterCFinalizerEx(socket, socket_finalizer, TRUE); @@ -138,6 +136,11 @@ SEXP rnng_protocol_open(SEXP protocol, SEXP dial, SEXP listen, SEXP tls, SEXP au UNPROTECT(1); return socket; + fail: + free(sock); + failmem: + ERROR_OUT(xc); + } SEXP rnng_close(SEXP socket) { @@ -189,15 +192,17 @@ static SEXP nano_stream_dial(SEXP url, SEXP textframes, SEXP tls) { const char *add = CHAR(STRING_ELT(url, 0)); if (tls != R_NilValue && NANO_PTR_CHECK(tls, nano_TlsSymbol)) Rf_error("'tls' is not a valid TLS Configuration"); - nano_stream *nst = calloc(1, sizeof(nano_stream)); - NANO_ENSURE_ALLOC(nst); - nst->mode = NANO_STREAM_DIALER; - nst->textframes = NANO_INTEGER(textframes) != 0; + nng_url *up = NULL; nng_aio *aiop = NULL; int xc; SEXP sd; + nano_stream *nst = calloc(1, sizeof(nano_stream)); + NANO_ENSURE_ALLOC(nst); + nst->mode = NANO_STREAM_DIALER; + nst->textframes = NANO_INTEGER(textframes) != 0; + if ((xc = nng_url_parse(&up, add)) || (xc = nng_stream_dialer_alloc_url(&nst->endpoint.dial, up)) || (xc = nng_aio_alloc(&aiop, NULL, NULL))) @@ -258,6 +263,7 @@ static SEXP nano_stream_dial(SEXP url, SEXP textframes, SEXP tls) { nng_stream_dialer_free(nst->endpoint.dial); nng_url_free(up); free(nst); + failmem: ERROR_OUT(xc); } @@ -267,15 +273,17 @@ static SEXP nano_stream_listen(SEXP url, SEXP textframes, SEXP tls) { const char *add = CHAR(STRING_ELT(url, 0)); if (tls != R_NilValue && NANO_PTR_CHECK(tls, nano_TlsSymbol)) Rf_error("'tls' is not a valid TLS Configuration"); - nano_stream *nst = calloc(1, sizeof(nano_stream)); - NANO_ENSURE_ALLOC(nst); - nst->mode = NANO_STREAM_LISTENER; - nst->textframes = NANO_INTEGER(textframes) != 0; + nng_url *up = NULL; nng_aio *aiop = NULL; int xc; SEXP sl; + nano_stream *nst = calloc(1, sizeof(nano_stream)); + NANO_ENSURE_ALLOC(nst); + nst->mode = NANO_STREAM_LISTENER; + nst->textframes = NANO_INTEGER(textframes) != 0; + if ((xc = nng_url_parse(&up, add)) || (xc = nng_stream_listener_alloc_url(&nst->endpoint.list, up)) || (xc = nng_aio_alloc(&aiop, NULL, NULL))) @@ -338,6 +346,7 @@ static SEXP nano_stream_listen(SEXP url, SEXP textframes, SEXP tls) { nng_stream_listener_free(nst->endpoint.list); nng_url_free(up); free(nst); + failmem: ERROR_OUT(xc); } diff --git a/src/sync.c b/src/sync.c index 88face89f..5e000d579 100644 --- a/src/sync.c +++ b/src/sync.c @@ -198,10 +198,10 @@ static void monitor_finalizer(SEXP xptr) { SEXP rnng_cv_alloc(void) { - nano_cv *cvp = calloc(1, sizeof(nano_cv)); - NANO_ENSURE_ALLOC(cvp); SEXP xp; int xc; + nano_cv *cvp = calloc(1, sizeof(nano_cv)); + NANO_ENSURE_ALLOC(cvp); if ((xc = nng_mtx_alloc(&cvp->mtx))) goto fail; @@ -219,6 +219,7 @@ SEXP rnng_cv_alloc(void) { fail: nng_mtx_free(cvp->mtx); free(cvp); + failmem: ERROR_OUT(xc); } @@ -427,6 +428,7 @@ SEXP rnng_request(SEXP con, SEXP data, SEXP sendmode, SEXP recvmode, SEXP timeou const nng_duration dur = timeout == R_NilValue ? NNG_DURATION_DEFAULT : (nng_duration) nano_integer(timeout); const uint8_t mod = (uint8_t) nano_matcharg(recvmode); + const int raw = nano_encodes(sendmode) == 2; const int id = msgid != R_NilValue ? NANO_INTEGER(msgid) : 0; int signal, drop, xc; if (cvar == R_NilValue) { @@ -437,37 +439,34 @@ SEXP rnng_request(SEXP con, SEXP data, SEXP sendmode, SEXP recvmode, SEXP timeou drop = 1 - signal; } + nano_saio *saio = NULL; + nano_aio *raio = NULL; + nng_ctx *ctx = NULL; + nng_msg *msg = NULL; SEXP aio, env, fun; nano_buf buf; - nng_msg *msg; - - nano_encodes(sendmode) == 2 ? nano_encode(&buf, data) : nano_serialize(&buf, data, NANO_PROT(con)); - nano_saio *saio = calloc(1, sizeof(nano_saio)); - if (saio == NULL) { - NANO_FREE(buf); - Rf_error("Memory allocation failed"); - } - nano_aio *raio = calloc(1, sizeof(nano_aio)); - if (raio == NULL) { - free(saio); - NANO_FREE(buf); - Rf_error("Memory allocation failed"); + if (raw) { + nano_encode(&buf, data); + } else { + nano_serialize(&buf, data, NANO_PROT(con)); } - nng_ctx *ctx; + + saio = calloc(1, sizeof(nano_saio)); + if (saio == NULL) + goto failmem; + + raio = calloc(1, sizeof(nano_aio)); + if (raio == NULL) + goto failmem; + if (sock) { nng_socket *sock = (nng_socket *) NANO_PTR(con); ctx = malloc(sizeof(nng_ctx)); - if (ctx == NULL) { - free(raio); - free(saio); - NANO_FREE(buf); - Rf_error("Memory allocation failed"); - } - if ((xc = nng_ctx_open(ctx, *sock))) { - free(ctx); + if (ctx == NULL) + goto failmem; + if ((xc = nng_ctx_open(ctx, *sock))) goto fail; - } } else { ctx = (nng_ctx *) NANO_PTR(con); } @@ -477,10 +476,8 @@ SEXP rnng_request(SEXP con, SEXP data, SEXP sendmode, SEXP recvmode, SEXP timeou saio->msgid = id; saio->alloc = sock; - if ((xc = nng_msg_alloc(&msg, 0))) - goto fail; - - if ((xc = nng_msg_append(msg, buf.buf, buf.cur)) || + if ((xc = nng_msg_alloc(&msg, 0)) || + (xc = nng_msg_append(msg, buf.buf, buf.cur)) || (xc = nng_aio_alloc(&saio->aio, sendaio_complete, saio))) { nng_msg_free(msg); goto fail; @@ -518,11 +515,19 @@ SEXP rnng_request(SEXP con, SEXP data, SEXP sendmode, SEXP recvmode, SEXP timeou fail: nng_aio_free(saio->aio); + if (sock) + free(ctx); free(raio); free(saio); NANO_FREE(buf); return mk_error_data(xc); + failmem: + free(raio); + free(saio); + NANO_FREE(buf); + Rf_error("Memory allocation failed"); + } SEXP rnng_set_promise_context(SEXP x, SEXP ctx) { @@ -662,17 +667,17 @@ SEXP rnng_monitor_create(SEXP socket, SEXP cv) { Rf_error("'cv' is not a valid Condition Variable"); const int n = 8; + SEXP xptr; + int xc; + nano_monitor *monitor = calloc(1, sizeof(nano_monitor)); NANO_ENSURE_ALLOC(monitor); monitor->ids = calloc(n, sizeof(int)); - NANO_ENSURE_ALLOC_FREE(monitor->ids, monitor); + NANO_ENSURE_ALLOC(monitor->ids); monitor->size = n; monitor->cv = (nano_cv *) NANO_PTR(cv); nng_socket *sock = (nng_socket *) NANO_PTR(socket); - SEXP xptr; - int xc; - if ((xc = nng_pipe_notify(*sock, NNG_PIPE_EV_ADD_POST, pipe_cb_monitor, monitor))) goto fail; @@ -688,7 +693,9 @@ SEXP rnng_monitor_create(SEXP socket, SEXP cv) { return xptr; fail: - free(monitor->ids); + failmem: + if (monitor != NULL) + free(monitor->ids); free(monitor); ERROR_OUT(xc); diff --git a/src/thread.c b/src/thread.c index da428ef70..a7cef12ef 100644 --- a/src/thread.c +++ b/src/thread.c @@ -134,31 +134,27 @@ static void rnng_messenger_thread(void *args) { SEXP rnng_messenger(SEXP url) { const char *up = CHAR(STRING_ELT(url, 0)); - nng_socket *sock = malloc(sizeof(nng_socket)); - NANO_ENSURE_ALLOC(sock); - nng_listener *lp; - nng_dialer *dp; + nng_listener *lp = NULL; + nng_dialer *dp = NULL; int xc, dialer = 0; SEXP socket, con; + nng_socket *sock = malloc(sizeof(nng_socket)); + NANO_ENSURE_ALLOC(sock); + if ((xc = nng_pair0_open(sock))) goto fail; lp = malloc(sizeof(nng_listener)); - if (lp == NULL) - goto failmem; + NANO_ENSURE_ALLOC(lp); if ((xc = nng_listen(*sock, up, lp, 0))) { - if (xc != 10 && xc != 15) { - free(lp); - goto failclose; - } + if (xc != 10 && xc != 15) + goto failmem; free(lp); + lp = NULL; dp = malloc(sizeof(nng_dialer)); - if (dp == NULL) + NANO_ENSURE_ALLOC(dp); + if ((xc = nng_dial(*sock, up, dp, 0))) goto failmem; - if ((xc = nng_dial(*sock, up, dp, 0))) { - free(dp); - goto failclose; - } dialer = 1; } @@ -176,17 +172,15 @@ SEXP rnng_messenger(SEXP url) { UNPROTECT(2); return socket; - failclose: - nng_close(*sock); + failmem: + free(dp); + free(lp); + if (sock != NULL) + nng_close(*sock); fail: free(sock); ERROR_OUT(xc); - failmem: - nng_close(*sock); - free(sock); - Rf_error("Memory allocation failed"); - } SEXP rnng_messenger_thread_create(SEXP args) { @@ -241,15 +235,19 @@ static void rnng_wait_thread_single(void *args) { void single_wait_thread_create(SEXP x) { nano_aio *aiop = (nano_aio *) NANO_PTR(x); - nano_thread_aio *taio = malloc(sizeof(nano_thread_aio)); + + int xc, signalled; + nano_thread_aio *taio = NULL; + nano_cv *ncv = NULL; + + taio = malloc(sizeof(nano_thread_aio)); NANO_ENSURE_ALLOC(taio); - nano_cv *ncv = malloc(sizeof(nano_cv)); - NANO_ENSURE_ALLOC_FREE(ncv, taio); + ncv = malloc(sizeof(nano_cv)); + NANO_ENSURE_ALLOC(ncv); taio->aio = aiop->aio; taio->cv = ncv; nng_mtx *mtx = NULL; nng_cv *cv = NULL; - int xc, signalled; if ((xc = nng_mtx_alloc(&mtx)) || (xc = nng_cv_alloc(&cv, mtx))) @@ -289,6 +287,7 @@ void single_wait_thread_create(SEXP x) { fail: nng_cv_free(cv); nng_mtx_free(mtx); + failmem: free(ncv); free(taio); ERROR_OUT(xc); @@ -489,6 +488,10 @@ SEXP rnng_signal_thread_create(SEXP cv, SEXP cv2) { if (NANO_PTR_CHECK(cv2, nano_CvSymbol)) Rf_error("'cv2' is not a valid Condition Variable"); + int xc; + nano_thread_duo *duo = malloc(sizeof(nano_thread_duo)); + NANO_ENSURE_ALLOC(duo); + SEXP existing = Rf_getAttrib(cv, R_MissingArg); if (existing != R_NilValue) { thread_duo_finalizer(existing); @@ -497,8 +500,6 @@ SEXP rnng_signal_thread_create(SEXP cv, SEXP cv2) { nano_cv *ncv = (nano_cv *) NANO_PTR(cv); nano_cv *ncv2 = (nano_cv *) NANO_PTR(cv2); - nano_thread_duo *duo = malloc(sizeof(nano_thread_duo)); - NANO_ENSURE_ALLOC(duo); duo->cv = ncv; duo->cv2 = ncv2; @@ -507,12 +508,8 @@ SEXP rnng_signal_thread_create(SEXP cv, SEXP cv2) { ncv->condition = 0; nng_mtx_unlock(dmtx); - const int xc = nng_thread_create(&duo->thr, rnng_signal_thread, duo); - if (xc) { - free(duo); - Rf_setAttrib(cv, R_MissingArg, R_NilValue); - ERROR_OUT(xc); - } + if ((xc = nng_thread_create(&duo->thr, rnng_signal_thread, duo))) + goto fail; SEXP xptr = R_MakeExternalPtr(duo, R_NilValue, R_NilValue); Rf_setAttrib(cv, R_MissingArg, xptr); @@ -520,4 +517,10 @@ SEXP rnng_signal_thread_create(SEXP cv, SEXP cv2) { return cv2; + fail: + free(duo); + Rf_setAttrib(cv, R_MissingArg, R_NilValue); + failmem: + ERROR_OUT(xc); + }