*/
static inline int appctx_init(struct appctx *appctx)
{
+ /* Set appctx affinity to the current thread. Because, after this call,
+ * the appctx will be fully initialized. The session and the stream will
+ * eventually be created. The affinity must be set now !
+ */
+ BUG_ON((appctx->t->thread_mask & tid_bit) == 0);
+ task_set_affinity(appctx->t, tid_bit);
+
if (appctx->applet->init)
return appctx->applet->init(appctx);
return 0;
{
struct appctx *appctx;
- /* Disable the feature for now ! */
- BUG_ON(thread_mask != tid_bit);
+ /* Backend appctx cannot be started on another thread than the local one */
+ BUG_ON(thread_mask != tid_bit && endp);
appctx = pool_zalloc(pool_head_appctx);
if (unlikely(!appctx))
{
struct session *sess;
- BUG_ON(appctx->sess || !(appctx->endp->flags & CS_EP_ORPHAN));
+ /* async startup is only possible for frontend appctx. Thus for orphan
+ * appctx. Because no backend appctx can be orphan.
+ */
+ BUG_ON(!(appctx->endp->flags & CS_EP_ORPHAN));
sess = session_new(px, NULL, &appctx->obj_type);
if (!sess)
struct task *task_run_applet(struct task *t, void *context, unsigned int state)
{
struct appctx *app = context;
- struct conn_stream *cs = appctx_cs(app);
+ struct conn_stream *cs;
unsigned int rate;
size_t count;
return NULL;
}
+ if (app->endp->flags & CS_EP_ORPHAN) {
+ /* Finalize init of orphan appctx. .init callback function must
+ * be defined and it must finalize appctx startup.
+ */
+ BUG_ON(!app->applet->init);
+
+ if (appctx_init(app) == -1) {
+ appctx_free_on_early_error(app);
+ return NULL;
+ }
+ BUG_ON(!app->sess || !appctx_cs(app) || !appctx_strm(app));
+ }
+
+ cs = appctx_cs(app);
+
/* We always pretend the applet can't get and doesn't want to
* put, it's up to it to change this if needed. This ensures
* that one applet which ignores any event will not spin.