~johill-lanl/epics-base/server1

« back to all changes in this revision

Viewing changes to src/cas/lib/SvrCirRspThrLuaHandle.cpp

  • Committer: Jeff Hill
  • Date: 2019-09-07 00:01:45 UTC
  • Revision ID: johill@lanl.gov-20190907000145-y99ilufpjbybp4xz
o added try/catch block to the response thread main loop
(there was already try/catch around event processing, but top level is needed to catch user Lua init errors and insufficent memory errors)
o use lua_pcall to call Lua context initialize and setupStack
o if there are undefined initialization symbols print a diagnostic message and allow the response thread to start

Show diffs side-by-side

added added

removed removed

Lines of Context:
115
115
    }
116
116
    lua_atpanic ( m_pLS, m_atPanic );
117
117
 
118
 
    m_initialize ();
119
 
    m_setupStack ();
 
118
    {
 
119
        // 
 
120
        // when m_initialize is finishing up it calls m_setupStackTop leaving
 
121
        // exactly top_last items on the stack for future use by the top
 
122
        // level context
 
123
        // 
 
124
        lua_pushcfunction ( m_pLS, & LuaHandle :: m_initialize );
 
125
        const int nArgPassedIn = 1;
 
126
        const int nArgPassedOut = top_last;
 
127
        lua_pushlightuserdata ( m_pLS, this );
 
128
        const int status = lua_pcall ( m_pLS, nArgPassedIn, nArgPassedOut, 0 );
 
129
        if ( status != LUA_OK ) {
 
130
            const char * pMsg = lua_tostring ( m_pLS, -1 );
 
131
            std :: string errctx = "cas: lua context initialization failed msg=\"";
 
132
            errctx += pMsg;
 
133
            errctx += "\"";
 
134
            lua_pop ( m_pLS, 1 );
 
135
            lua_close ( m_pLS ); 
 
136
            m_pLS = 0;
 
137
            throw runtime_error ( errctx );
 
138
        }
 
139
    }
 
140
    m_verifyStackTop ();
120
141
}
121
142
 
122
143
void RspThr :: LuaHandle :: shutdown ()
313
334
}
314
335
#endif /* ifdef CAS_LUA_DONT_USE_REALLOC */
315
336
 
316
 
#pragma message ("should eventually use pcall")
317
 
void RspThr :: LuaHandle :: m_initialize ()
 
337
int RspThr :: LuaHandle :: m_initialize ( lua_State * const pLS )
318
338
{
319
 
    if ( ! m_pLS ) {
320
 
        return;
321
 
    }
 
339
    const int arg_this = 1;
 
340
    RspThr :: LuaHandle * const pThis = static_cast < RspThr :: LuaHandle * > 
 
341
                                            ( lua_touserdata ( pLS, arg_this ) );
 
342
    assert ( pThis && pLS && pThis->m_pLS &&  pLS == pThis->m_pLS );
322
343
 
323
344
    //
324
345
    // stop garbage collector during initialization
325
346
    //
326
 
    lua_gc ( m_pLS, LUA_GCSTOP, 0 );  
 
347
    lua_gc ( pLS, LUA_GCSTOP, 0 );  
327
348
 
328
349
    for ( const luaL_Reg * pReg = luaLibList; 
329
350
            pReg->func; pReg++ ) {
330
 
        luaL_requiref ( m_pLS, pReg->name, pReg->func, 1 );
 
351
        luaL_requiref ( pLS, pReg->name, pReg->func, 1 );
331
352
        // Lua Stack
332
353
        // (1) table containing library
333
 
        lua_pop ( m_pLS, 1);
 
354
        lua_pop ( pLS, 1 );
334
355
        // Lua Stack
335
356
        // <empty>
336
357
    }
337
358
 
338
 
    int callLoadStatus = load_luacontext_lua ( m_pLS );
 
359
    int callLoadStatus = load_luacontext_lua ( pLS );
339
360
    if ( callLoadStatus != LUA_OK ) {
340
 
        const char * pMsg = lua_tostring ( m_pLS, -1 );
 
361
        const char * pMsg = lua_tostring ( pLS, -1 );
341
362
        std :: string errctx = "cas: lua initialization failed ctx=\"";
342
363
        errctx += pMsg;
343
364
        errctx += "\"";
344
 
        lua_pop ( m_pLS, 1 );
 
365
        lua_pop ( pLS, 1 );
345
366
        throw runtime_error ( errctx );
346
367
    }
347
368
    
354
375
                const lua_CFunction pCASLuaStartup = 
355
376
                            ( lua_CFunction ) registryFunctionFind ( token );
356
377
                if ( pCASLuaStartup ) {
357
 
                    callLoadStatus = ( *pCASLuaStartup ) ( m_pLS );
 
378
                    callLoadStatus = ( *pCASLuaStartup ) ( pLS );
358
379
                    if ( callLoadStatus != LUA_OK ) {
 
380
                        //
 
381
                        // incomplete initialization probably spells trouble
 
382
                        // so we throw an exception and in all probability dont 
 
383
                        // allow any additional incoming connections until the 
 
384
                        // problem is corrected
 
385
                        //
359
386
                        const char * pMsg = lua_tostring ( m_pLS, -1 );
360
387
                        std :: string errctx = "cas: Lua startup function \"";
361
388
                        errctx += token;
367
394
                    }
368
395
                }
369
396
                else {
370
 
                    std :: string errctx = "cas: Lua startup function \"";
371
 
                    errctx += token;
372
 
                    errctx += "\" not found in the registry";
373
 
                    throw runtime_error ( errctx );
 
397
                    //
 
398
                    // an undefined initialization symbol is ok to ignore after
 
399
                    // providing a diagnostic for the log file
 
400
                    //
 
401
                    errlogPrintf ( 
 
402
                        "cas: Lua startup function \"%s\" is undefined in the registry\n", 
 
403
                        token );
374
404
                }
375
405
            }
376
406
        }
377
407
    }
378
408
 
379
 
 
380
409
    /*
381
410
     * LANSCE specific code obviously needs to be moved elsewhere
382
411
     */
383
 
    callLoadStatus = load_lualansce_lua ( m_pLS );
 
412
    callLoadStatus = load_lualansce_lua ( pLS );
384
413
    if ( callLoadStatus != LUA_OK ) {
385
 
        const char * pMsg = lua_tostring ( m_pLS, -1 );
 
414
        const char * pMsg = lua_tostring ( pLS, -1 );
386
415
        std :: string errctx = "cas: lua LANSCE initialization failed ctx=\"";
387
416
        errctx += pMsg;
388
417
        errctx += "\"";
389
 
        lua_pop ( m_pLS, 1 );
 
418
        lua_pop ( pLS, 1 );
390
419
        throw runtime_error ( errctx );
391
420
    }
392
421
 
394
423
    // set Lua global "flavorFilterFunctionLuaFactory" to be the C
395
424
    // function LANSCE :: flavorFilterFunctionLuaFactory
396
425
    //
397
 
    lua_register ( m_pLS, "flavorFilterFunctionLuaFactory", 
 
426
    lua_register ( pLS, "flavorFilterFunctionLuaFactory", 
398
427
                    LANSCE :: flavorFilterFunctionLuaFactory );
399
428
    //
400
429
    // set Lua global "flavorFilterFunctionLuaFactory" to be the C
401
430
    // function LANSCE :: flavorFilterFunctionLuaFactory
402
431
    //
403
 
    lua_register ( m_pLS, "timeFilterFunctionLuaFactory", 
 
432
    lua_register ( pLS, "timeFilterFunctionLuaFactory", 
404
433
                    LANSCE :: timeFilterFunctionLuaFactory );
405
434
 
406
435
    //
416
445
    // These are intermittently used so its important to verify
417
446
    // that they exist during startup
418
447
    //
419
 
    m_verifyFunc ( "casChannelFactoryDefault" );
 
448
    pThis->m_verifyFunc ( "casChannelFactoryDefault" );
420
449
 
421
450
    //
422
451
    // restart garbage collector after initialization is complete
423
452
    //
424
 
    lua_gc ( m_pLS, LUA_GCRESTART, 0);
 
453
    lua_gc ( pLS, LUA_GCRESTART, 0);
 
454
 
 
455
    //
 
456
    // initialize stack and leave exactly top_last items there,
 
457
    // but first remove arg_this so we start with the stack at 
 
458
    // its top which probably avoids a stack copy when pcall returns
 
459
    //
 
460
    lua_pop ( pLS, 1 ); 
 
461
    // returning the number of items pushed onto the stack
 
462
    return pThis->m_setupStackTop ();
425
463
}
426
464
 
427
465
int RspThr :: LuaHandle :: m_atPanic ( lua_State * pLS )
575
613
    }
576
614
}
577
615
 
578
 
#pragma message ("should eventually use pcall")
579
 
void RspThr :: LuaHandle :: m_setupStack ()
580
 
{
581
 
    if ( ! m_pLS ) {
582
 
        return;
583
 
    }
 
616
// BEWARE, these are indexes into the top level Lua call frame,
 
617
// for calling expediantly into C closures in Lua. They will be 
 
618
// rejected by Lua and or produce undefined behaior if they are 
 
619
// used in a Lua callback into C, or from within a C function 
 
620
// called by call or pcall 
 
621
void RspThr :: LuaHandle :: m_verifyStackTop ()
 
622
{
 
623
    luaL_checktype ( m_pLS, top_traceback, LUA_TFUNCTION );
 
624
    luaL_checktype ( m_pLS, top_channelInstall, LUA_TFUNCTION );
 
625
    luaL_checktype ( m_pLS, top_channelFactorySyntaxError, LUA_TFUNCTION );
 
626
    luaL_checktype ( m_pLS, top_channelUninstall, LUA_TFUNCTION );
 
627
    luaL_checktype ( m_pLS, top_subscrFilter, LUA_TFUNCTION );
 
628
    luaL_checktype ( m_pLS, top_subscrFilterAlwaysFalseFactory, LUA_TFUNCTION );
 
629
    luaL_checktype ( m_pLS, top_subscrFilterUninstall, LUA_TFUNCTION );
 
630
    LuaHandle :: verifyAtTop ( *m_pLS );
 
631
}
 
632
 
 
633
int RspThr :: LuaHandle :: m_setupStackTop ()
 
634
{
 
635
    assert ( m_pLS );
584
636
    luaL_checkstack ( m_pLS, 16, 0 );
585
637
    lua_newtable ( m_pLS ); // channel table
586
638
    lua_newtable ( m_pLS ); // filter table
592
644
    lua_pushcfunction ( m_pLS, 
593
645
            & RspThr :: ChanCreate :: pushClosure_m_installLuaChannel );
594
646
    lua_pushvalue ( m_pLS, idx_channelTable );
595
 
    assert ( lua_pcall ( m_pLS, 1, 1, 0 ) == LUA_OK );
 
647
    lua_call ( m_pLS, 1, 1 );
596
648
 
597
649
    // call RspThr :: ChanCreate :: pushClosure_m_channelFactorySyntaxError
598
650
    lua_pushcfunction ( m_pLS, 
599
651
            & RspThr :: ChanCreate :: 
600
652
                            pushClosure_m_channelFactorySyntaxError );
601
653
    lua_pushvalue ( m_pLS, idx_channelTable );
602
 
    assert ( lua_pcall ( m_pLS, 1, 1, 0 ) == LUA_OK );
 
654
    lua_call ( m_pLS, 1, 1 );
603
655
    
604
656
    // call RspThr :: ChanDestroy :: pushClosure_m_uninstallChannel
605
657
    lua_pushcfunction ( m_pLS, 
606
658
            & RspThr :: ChanDestroy :: pushClosure_m_uninstallChannel );
607
659
    lua_pushvalue ( m_pLS, idx_channelTable );
608
 
    assert ( lua_pcall ( m_pLS, 1, 1, 0 ) == LUA_OK );
 
660
    lua_call ( m_pLS, 1, 1);
609
661
 
610
662
    // call m_pushFilterClosure
611
663
    lua_pushcfunction ( m_pLS, 
612
664
            & RspThr :: Subscribe :: pushClosure_m_filter );
613
665
    lua_pushvalue  ( m_pLS, idx_channelTable );
614
666
    lua_pushvalue  ( m_pLS, idx_filterTable );
615
 
    assert ( lua_pcall ( m_pLS, 2, 1, 0 ) == LUA_OK );
 
667
    lua_call ( m_pLS, 2, 1 );
616
668
 
617
669
    lua_pushcfunction ( m_pLS, 
618
670
            & RspThr :: Subscribe :: pushClosure_m_filterAlwaysFalseFactory );
619
671
    lua_pushvalue  ( m_pLS, idx_filterTable );
620
 
    assert ( lua_pcall ( m_pLS, 1, 1, 0 ) == LUA_OK );
 
672
    lua_call ( m_pLS, 1, 1 );
621
673
 
622
674
    // call m_pushFilterUnistallClosure
623
675
    lua_pushcfunction ( m_pLS, 
624
676
            & RspThr :: Subscribe :: pushClosure_m_filterUninstall );
625
677
    lua_pushvalue  ( m_pLS, idx_filterTable );
626
 
    assert ( lua_pcall ( m_pLS, 1, 1, 0 ) == LUA_OK );
 
678
    lua_call ( m_pLS, 1, 1 );
627
679
 
628
680
    // sanity check the newly initialized Lua stack
629
681
    lua_remove ( m_pLS, 1 );
630
682
    lua_remove ( m_pLS, 1 );
631
 
    // BEWARE, these are indexes into the top level Lua call frame,
632
 
    // for calling expediantly into C closures in Lua. They will be 
633
 
    // rejected by Lua and or produce undefined behaior if they are 
634
 
    // used in a Lua callback into C, or from within a C function 
635
 
    // called by call or pcall 
636
 
    luaL_checktype ( m_pLS, top_traceback, LUA_TFUNCTION );
637
 
    luaL_checktype ( m_pLS, top_channelInstall, LUA_TFUNCTION );
638
 
    luaL_checktype ( m_pLS, top_channelFactorySyntaxError, LUA_TFUNCTION );
639
 
    luaL_checktype ( m_pLS, top_channelUninstall, LUA_TFUNCTION );
640
 
    luaL_checktype ( m_pLS, top_subscrFilter, LUA_TFUNCTION );
641
 
    luaL_checktype ( m_pLS, top_subscrFilterAlwaysFalseFactory, LUA_TFUNCTION );
642
 
    luaL_checktype ( m_pLS, top_subscrFilterUninstall, LUA_TFUNCTION );
643
 
    LuaHandle :: verifyAtTop ( *m_pLS );
 
683
    // returning the number of items pushed onto the stack
 
684
    return top_last;
644
685
}
645
686
 
646
687
void RspThr :: LuaHandle :: m_cleanupStack () epicsNoexcept