Skip to content

Commit ace137e

Browse files
committed
Fix race when counting pins open for tests
The unit tests check that pins properly get cleaned up, but there was a race condition. This fixes this by using atomics. Since keeping open pin counts was intended as a test-only feature and there's a chance of the use of atomics creating compilation issues, demote the pin count handling to the stub backend only.
1 parent e4971a1 commit ace137e

File tree

3 files changed

+15
-10
lines changed

3 files changed

+15
-10
lines changed

c_src/gpio_nif.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ static void release_gpio_pin(struct gpio_priv *priv, struct gpio_pin *pin)
2020
{
2121
if (pin->fd >= 0) {
2222
hal_close_gpio(pin);
23-
priv->pins_open--;
2423
pin->fd = -1;
2524
}
2625
}
@@ -104,7 +103,6 @@ static int load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM info)
104103
return 1;
105104
}
106105

107-
priv->pins_open = 0;
108106
priv->gpio_pin_rt = enif_open_resource_type_x(env, "gpio_pin", &gpio_pin_init, ERL_NIF_RT_CREATE, NULL);
109107

110108
if (hal_load(&priv->hal_priv) < 0) {
@@ -331,8 +329,6 @@ static ERL_NIF_TERM open_gpio(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[
331329
ERL_NIF_TERM pin_resource = enif_make_resource(env, pin);
332330
enif_release_resource(pin);
333331

334-
priv->pins_open++;
335-
336332
return make_ok_tuple(env, pin_resource);
337333
}
338334

@@ -356,8 +352,6 @@ static ERL_NIF_TERM gpio_info(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[
356352
struct gpio_priv *priv = enif_priv_data(env);
357353
ERL_NIF_TERM info = enif_make_new_map(env);
358354

359-
enif_make_map_put(env, info, enif_make_atom(env, "pins_open"), enif_make_int(env, priv->pins_open), &info);
360-
361355
return hal_info(env, priv->hal_priv, info);
362356
}
363357

c_src/gpio_nif.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ enum pull_mode {
4646
struct gpio_priv {
4747
ErlNifResourceType *gpio_pin_rt;
4848

49-
int pins_open;
50-
5149
uint32_t hal_priv[1];
5250
};
5351

c_src/hal_stub.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// SPDX-License-Identifier: Apache-2.0
44

55
#include "gpio_nif.h"
6+
7+
#include <stdatomic.h>
68
#include <string.h>
79

810
#define NUM_GPIOS 64
@@ -13,16 +15,19 @@
1315
*/
1416

1517
struct stub_priv {
18+
atomic_int pins_open;
1619
int value[NUM_GPIOS / 2];
1720
ErlNifPid pid[NUM_GPIOS];
1821
enum trigger_mode mode[NUM_GPIOS];
1922
};
2023

2124
ERL_NIF_TERM hal_info(ErlNifEnv *env, void *hal_priv, ERL_NIF_TERM info)
2225
{
23-
(void) hal_priv;
26+
struct stub_priv *stub_priv = (struct stub_priv *) hal_priv;
27+
int pins_open = atomic_load(&stub_priv->pins_open);
2428

2529
enif_make_map_put(env, info, enif_make_atom(env, "name"), enif_make_atom(env, "stub"), &info);
30+
enif_make_map_put(env, info, enif_make_atom(env, "pins_open"), enif_make_int(env, pins_open), &info);
2631
return info;
2732
}
2833

@@ -33,7 +38,11 @@ size_t hal_priv_size(void)
3338

3439
int hal_load(void *hal_priv)
3540
{
36-
memset(hal_priv, 0, sizeof(struct stub_priv));
41+
struct stub_priv *stub_priv = (struct stub_priv *) hal_priv;
42+
43+
memset(stub_priv, 0, sizeof(struct stub_priv));
44+
stub_priv->pins_open = 0;
45+
3746
return 0;
3847
}
3948

@@ -49,7 +58,10 @@ int hal_open_gpio(struct gpio_pin *pin,
4958
(void) env;
5059
// For test purposes, pins 0-63 work and everything else fails
5160
if (pin->pin_number >= 0 && pin->pin_number < NUM_GPIOS) {
61+
struct stub_priv *stub_priv = pin->hal_priv;
62+
5263
pin->fd = pin->pin_number;
64+
atomic_fetch_add(&stub_priv->pins_open, 1);
5365

5466
if (pin->config.is_output && pin->config.initial_value != -1)
5567
hal_write_gpio(pin, pin->config.initial_value, env);
@@ -67,6 +79,7 @@ void hal_close_gpio(struct gpio_pin *pin)
6779
if (pin->fd >= 0) {
6880
struct stub_priv *hal_priv = pin->hal_priv;
6981
hal_priv->mode[pin->pin_number] = TRIGGER_NONE;
82+
atomic_fetch_sub(&hal_priv->pins_open, 1);
7083
pin->fd = -1;
7184
}
7285
}

0 commit comments

Comments
 (0)