1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

sequencer: add second aux message arg

Since the messages are queued and then read in order from the event loop
thread, it's not generally safe to pass pointers to argument structs,
since there's no guarantee the lifetime of the thing sending the message
lasted until the sequencer read the message.

This puts pressure on the single void * argument-passed-as-value... this patch
adds a second void * argument-passed-as-value so it's more possible to put
what's needed directly in the argument.

It's also possible to alloc the argument on the heap and have the sequencer
callback free it after it has read it.
This commit is contained in:
Andy Green 2019-08-07 10:41:03 +01:00
parent 20923db2b5
commit 1d954d52a3
7 changed files with 63 additions and 30 deletions

View file

@ -70,7 +70,8 @@ typedef struct lws_sequencer lws_sequencer_t; /* opaque */
* starting from LWSSEQ_USER_BASE.
*/
typedef lws_seq_cb_return_t (*lws_seq_event_cb)(struct lws_sequencer *seq,
void *user, int event, void *data);
void *user, int event, void *data, void *aux);
typedef struct lws_seq_info {
struct lws_context *context; /* lws_context for seq */
int tsi; /* thread service idx */
@ -113,18 +114,25 @@ LWS_VISIBLE LWS_EXTERN void
lws_sequencer_destroy(lws_sequencer_t **seq);
/**
* lws_sequencer_event() - queue an event on the given sequencer
* lws_sequencer_queue_event() - queue an event on the given sequencer
*
* \param seq: the opaque sequencer pointer returned by lws_sequencer_create()
* \param e: the event index to queue
* \param data: associated opaque (to lws) data to provide the callback
* \param aux: second opaque data to provide the callback
*
* This queues the event on a given sequencer. Queued events are delivered one
* per sequencer each subsequent time around the event loop, so the cb is called
* from the event loop thread context.
*
* Notice that because the events are delivered in order from the event loop,
* the scope of objects pointed to by \p data or \p aux may exceed the lifetime
* of the thing containing the pointed-to data. So it's usually better to pass
* values here.
*/
LWS_VISIBLE LWS_EXTERN int
lws_sequencer_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data);
lws_sequencer_queue_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data,
void *aux);
/**
* lws_sequencer_check_wsi() - check if wsi still extant
@ -210,3 +218,14 @@ lws_sequencer_secs_since_creation(lws_sequencer_t *seq);
*/
LWS_VISIBLE LWS_EXTERN const char *
lws_sequencer_name(lws_sequencer_t *seq);
/**
* lws_sequencer_get_context(): get the lws_context sequencer was created on
*
* \param seq: pointer to the lws_sequencer_t
*
* Returns the lws_context. Saves you having to store it if you have a seq
* pointer handy.
*/
LWS_VISIBLE LWS_EXTERN struct lws_context *
lws_sequencer_get_context(lws_sequencer_t *seq);

View file

@ -88,7 +88,7 @@ unit_test_result_cb(const void *cb_user, int disposition)
return -1;
}
lws_sequencer_event(s->unit_test_seq, r, NULL);
lws_sequencer_queue_event(s->unit_test_seq, r, NULL, NULL);
((struct lws_seq_test_sequencer *)s)->instance = NULL;
@ -103,7 +103,8 @@ unit_test_result_cb(const void *cb_user, int disposition)
*/
static lws_seq_cb_return_t
test_sequencer_cb(struct lws_sequencer *seq, void *user, int event, void *data)
test_sequencer_cb(struct lws_sequencer *seq, void *user, int event, void *data,
void *aux)
{
struct lws_seq_test_sequencer *s =
(struct lws_seq_test_sequencer *)user;

View file

@ -97,7 +97,8 @@ callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason,
* our lifecycle events
*/
lws_sequencer_event(wsi->seq, LWSSEQ_WSI_CONNECTED, wsi);
lws_sequencer_queue_event(wsi->seq, LWSSEQ_WSI_CONNECTED,
wsi, NULL);
break;
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
@ -111,8 +112,8 @@ callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason,
* our lifecycle events
*/
lws_sequencer_event(wsi->seq, LWSSEQ_WSI_CONN_FAIL,
wsi);
lws_sequencer_queue_event(wsi->seq, LWSSEQ_WSI_CONN_FAIL,
wsi, NULL);
goto close_path;
@ -127,8 +128,8 @@ callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason,
* our lifecycle events
*/
lws_sequencer_event(wsi->seq, LWSSEQ_WSI_CONN_CLOSE,
wsi);
lws_sequencer_queue_event(wsi->seq, LWSSEQ_WSI_CONN_CLOSE,
wsi, NULL);
close_path:
lwsl_debug("LWS_CALLBACK_RAW_CLOSE\n");

View file

@ -78,7 +78,8 @@ lws_unit_test_packet_dispose(abs_unit_test_priv_t *priv,
priv->disposition = disp;
lws_sequencer_event(priv->seq, UTSEQ_MSG_DISPOSITION_KNOWN, NULL);
lws_sequencer_queue_event(priv->seq, UTSEQ_MSG_DISPOSITION_KNOWN,
NULL, NULL);
return disp;
}
@ -125,7 +126,7 @@ process_expect(abs_unit_test_priv_t *priv)
static lws_seq_cb_return_t
unit_test_sequencer_cb(struct lws_sequencer *seq, void *user, int event,
void *data)
void *data, void *aux)
{
seq_priv_t *s = (seq_priv_t *)user;
abs_unit_test_priv_t *priv = (abs_unit_test_priv_t *)s->ai->ati;
@ -280,7 +281,7 @@ lws_atcut_close(lws_abs_transport_inst_t *ati)
lwsl_notice("%s\n", __func__);
lws_sequencer_event(priv->seq, UTSEQ_MSG_CLOSING, NULL);
lws_sequencer_queue_event(priv->seq, UTSEQ_MSG_CLOSING, NULL, NULL);
return 0;
}
@ -332,7 +333,7 @@ lws_atcut_tx(lws_abs_transport_inst_t *ati, uint8_t *buf, size_t len)
priv->expect++;
lws_sequencer_event(priv->seq, UTSEQ_MSG_POST_TX_KICK, NULL);
lws_sequencer_queue_event(priv->seq, UTSEQ_MSG_POST_TX_KICK, NULL, NULL);
return 0;
}
@ -382,7 +383,7 @@ lws_atcut_client_conn(const lws_abs_t *abs)
lwsl_notice("%s: %s: test '%s': start\n", __func__, abs->ap->name,
priv->current_test->name);
lws_sequencer_event(priv->seq, UTSEQ_MSG_CONNECTING, NULL);
lws_sequencer_queue_event(priv->seq, UTSEQ_MSG_CONNECTING, NULL, NULL);
return 0;
}
@ -401,7 +402,7 @@ lws_atcut_ask_for_writeable(lws_abs_transport_inst_t *ati)
* until we have returned to the event loop, just like a real
* callback_on_writable()
*/
lws_sequencer_event(priv->seq, UTSEQ_MSG_WRITEABLE, NULL);
lws_sequencer_queue_event(priv->seq, UTSEQ_MSG_WRITEABLE, NULL, NULL);
return 0;
}

View file

@ -28,6 +28,7 @@ typedef struct lws_seq_event {
struct lws_dll2 seq_event_list;
void *data;
void *aux;
lws_seq_events_t e;
} lws_seq_event_t;
@ -81,7 +82,7 @@ lws_sequencer_create(lws_seq_info_t *i)
/* try to queue the creation cb */
if (lws_sequencer_event(seq, LWSSEQ_CREATED, NULL)) {
if (lws_sequencer_queue_event(seq, LWSSEQ_CREATED, NULL, NULL)) {
lws_dll2_remove(&seq->seq_list);
lws_free(seq);
@ -111,7 +112,7 @@ lws_sequencer_destroy(lws_sequencer_t **pseq)
/* defeat another thread racing to add events while we are destroying */
seq->going_down = 1;
seq->cb(seq, (void *)&seq[1], LWSSEQ_DESTROYED, NULL);
seq->cb(seq, (void *)&seq[1], LWSSEQ_DESTROYED, NULL, NULL);
lws_pt_lock(seq->pt, __func__); /* -------------------------- pt { */
@ -141,7 +142,8 @@ lws_sequencer_destroy_all_on_pt(struct lws_context_per_thread *pt)
}
int
lws_sequencer_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data)
lws_sequencer_queue_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data,
void *aux)
{
lws_seq_event_t *seqe;
@ -154,6 +156,7 @@ lws_sequencer_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data)
seqe->e = e;
seqe->data = data;
seqe->aux = aux;
// lwsl_notice("%s: seq %s: event %d\n", __func__, seq->name, e);
@ -233,7 +236,7 @@ lws_sequencer_next_event(struct lws_dll2 *d, void *user)
dh = lws_dll2_get_head(&seq->seq_event_owner);
seqe = lws_container_of(dh, lws_seq_event_t, seq_event_list);
n = seq->cb(seq, (void *)&seq[1], seqe->e, seqe->data);
n = seq->cb(seq, (void *)&seq[1], seqe->e, seqe->data, seqe->aux);
/* ... have to lock here though, because we will change the list */
@ -342,7 +345,8 @@ lws_sequencer_timeout_check(struct lws_context_per_thread *pt, time_t now)
/* seq has timed out... remove him from timeout list */
lws_sequencer_timeout(s, 0);
/* queue the message to inform the sequencer */
lws_sequencer_event(s, LWSSEQ_TIMED_OUT, NULL);
lws_sequencer_queue_event(s, LWSSEQ_TIMED_OUT,
NULL, NULL);
} else
/*
* No need to look further if we met one later than now:
@ -360,7 +364,7 @@ lws_sequencer_timeout_check(struct lws_context_per_thread *pt, time_t now)
seq_list);
/* queue the message to inform the sequencer */
lws_sequencer_event(s, LWSSEQ_HEARTBEAT, NULL);
lws_sequencer_queue_event(s, LWSSEQ_HEARTBEAT, NULL, NULL);
} lws_end_foreach_dll_safe(p, tp);
@ -388,3 +392,10 @@ lws_sequencer_secs_since_creation(lws_sequencer_t *seq)
return now - seq->time_created;
}
struct lws_context *
lws_sequencer_get_context(lws_sequencer_t *seq)
{
return seq->pt->context;
}

View file

@ -143,7 +143,7 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info,
private_key_filepath))
return 1;
lwsl_notice("created client ssl context for %s\n", vhost->name);
lwsl_info("created client ssl context for %s\n", vhost->name);
/*
* give him a fake wsi with context set, so he can use

View file

@ -35,7 +35,6 @@ enum {
*/
struct myseq {
struct lws_context *context;
struct lws_vhost *vhost;
struct lws *cwsi; /* client wsi for current step if any */
@ -163,7 +162,8 @@ notify:
lws_set_wsi_user(wsi, NULL);
s->cwsi = NULL;
lws_sequencer_event(lws_sequencer_from_user(s), seq_msg, NULL);
lws_sequencer_queue_event(lws_sequencer_from_user(s), seq_msg,
NULL, NULL);
return 0;
}
@ -185,7 +185,7 @@ sequencer_start_client(struct myseq *s)
lws_strncpy(uri, url_paths[s->state], sizeof(uri));
memset(&i, 0, sizeof i);
i.context = s->context;
i.context = lws_sequencer_get_context(lws_sequencer_from_user(s));
if (lws_parse_uri(uri, &prot, &i.address, &i.port, &path1)) {
lwsl_err("%s: uri error %s\n", __func__, uri);
@ -217,8 +217,8 @@ sequencer_start_client(struct myseq *s)
/* we couldn't even get started with the client connection */
lws_sequencer_event(lws_sequencer_from_user(s),
SEQ_MSG_CLIENT_FAILED, NULL);
lws_sequencer_queue_event(lws_sequencer_from_user(s),
SEQ_MSG_CLIENT_FAILED, NULL, NULL);
return 1;
}
@ -238,7 +238,8 @@ sequencer_start_client(struct myseq *s)
*/
static lws_seq_cb_return_t
sequencer_cb(struct lws_sequencer *seq, void *user, int event, void *data)
sequencer_cb(struct lws_sequencer *seq, void *user, int event,
void *data, void *aux)
{
struct myseq *s = (struct myseq *)user;
@ -382,7 +383,6 @@ main(int argc, const char **argv)
lwsl_err("%s: unable to create sequencer\n", __func__);
goto bail1;
}
s->context = context;
s->vhost = vh;
/* the usual lws event loop */