33#include < algorithm>
44#include < mutex>
55#include < shared_mutex>
6+ #include < thread>
67
78#include < stdcorelib/path.h>
89#include < stdcorelib/pimpl.h>
@@ -88,11 +89,21 @@ namespace srt::g2p {
8889 srt::core::Expected<void > Manager::initialize () {
8990 auto &impl = *static_cast <PackageManager::Impl *>(_impl.get ());
9091
92+ // Thread safety: prevent concurrent entry. Without this lock, two
93+ // threads calling initializeModels() simultaneously (e.g.
94+ // InitInferEngineTask + GetPronunciationTask) could both pass the
95+ // m_initialized check and enter the init path together, causing
96+ // state corruption or hangs in ONNX session creation.
97+ std::lock_guard<std::mutex> initLock (impl.m_init_mtx );
98+
9199 if (impl.m_initialized ) {
92100 return Error (ErrorCode::G2pAlreadyInitialized,
93101 " Manager::initialize() has already been called" );
94102 }
95103
104+ g2pLog.srtInfo (" Manager::initialize: START (thread=%1)" ,
105+ std::hash<std::thread::id>{}(std::this_thread::get_id ()));
106+
96107 // Phase 1: Default context (official G2P).
97108 // Allow empty default context: when no official G2P packages are
98109 // registered (voicebank-only deployment), skip Phase 1 entirely and
@@ -101,8 +112,11 @@ namespace srt::g2p {
101112 // honors ds-session.md §210: "某 G2P module 初始化失败:仅关联
102113 // singer-language Disabled,其他语言/声库仍可发布".
103114 {
115+ g2pLog.srtInfo (" Manager::initialize: Phase 1 (default context) START" );
104116 srt::core::ContextKey defaultCtx (" " );
105117 const auto moduleInfos = this ->getModuleMetadatas (defaultCtx);
118+ g2pLog.srtInfo (" Manager::initialize: Phase 1 moduleMetadatas count=%1" ,
119+ moduleInfos.size ());
106120 if (moduleInfos.empty ()) {
107121 // Diagnostic: log registered paths and their filesystem status
108122 // to identify why the default context has no modules. Remove
@@ -158,26 +172,40 @@ namespace srt::g2p {
158172 }
159173
160174 auto packageOrder = depGraph.getPackageInitializationOrder ();
175+ g2pLog.srtInfo (" Manager::initialize: Phase 1 packageOrder size=%1" ,
176+ packageOrder.size ());
161177 int failedPkgCount = 0 ;
162178 std::vector<std::string> pkgErrors;
163179 for (const auto &packageInfo : packageOrder) {
180+ g2pLog.srtInfo (" Manager::initialize: Phase 1 opening package=%1 path=%2" ,
181+ packageInfo.packageId ,
182+ stdc::path::to_utf8 (packageInfo.packagePath ));
164183 auto exp = this ->open (packageInfo.packagePath );
165184 if (!exp) {
185+ g2pLog.srtWarning (" Manager::initialize: Phase 1 open FAILED package=%1: %2" ,
186+ packageInfo.packageId , exp.error ().message ());
166187 pkgErrors.push_back (packageInfo.packageId + " : " + exp.error ().message ());
167188 failedPkgCount++;
168189 continue ;
169190 }
170191
171192 Package pkg = exp.take ();
172193 if (!pkg.isLoaded ()) {
194+ g2pLog.srtWarning (" Manager::initialize: Phase 1 pkg not loaded package=%1: %2" ,
195+ packageInfo.packageId , pkg.error ().message ());
173196 pkgErrors.push_back (packageInfo.packageId + " : " + pkg.error ().message ());
174197 failedPkgCount++;
175198 continue ;
176199 }
177200
201+ g2pLog.srtInfo (" Manager::initialize: Phase 1 package=%1 loaded, creating %2 tasks" ,
202+ packageInfo.packageId , packageInfo.initializationOrder .size ());
178203 for (const auto &moduleInfo : packageInfo.initializationOrder ) {
204+ g2pLog.srtInfo (" Manager::initialize: Phase 1 creating task module=%1 type=%2 iid=%3" ,
205+ moduleInfo.moduleId , moduleInfo.type , moduleInfo.iid );
179206 auto taskExp = createModuleTask (moduleInfo, pkg);
180207 if (taskExp) {
208+ g2pLog.srtInfo (" Manager::initialize: Phase 1 task created OK module=%1" , moduleInfo.moduleId );
181209 const auto fqid = ContextUtils::formatFqid (defaultCtx, moduleInfo.moduleId );
182210 if (auto *cate = this ->category (moduleInfo.type )) {
183211 cate->addObject (fqid, taskExp.value ());
@@ -199,23 +227,31 @@ namespace srt::g2p {
199227 }
200228
201229 impl.m_contextStates [defaultCtx] = ContextState::Ready;
230+ g2pLog.srtInfo (" Manager::initialize: Phase 1 default context Ready" );
202231 }
203232 }
204233 }
234+ g2pLog.srtInfo (" Manager::initialize: Phase 1 END" );
205235
206236 // Phase 2: Non-default contexts
237+ g2pLog.srtInfo (" Manager::initialize: Phase 2 START, contextPaths=%1" ,
238+ impl.m_contextPackagePaths .size ());
207239 for (const auto &[ctxKey, _] : impl.m_contextPackagePaths ) {
208240 if (ctxKey.isDefault ())
209241 continue ;
210242
243+ g2pLog.srtInfo (" Manager::initialize: Phase 2 context=%1 v=%2 START" ,
244+ ctxKey.context , ctxKey.version .toString ());
211245 const auto moduleInfos = this ->getModuleMetadatas (ctxKey);
212246 if (moduleInfos.empty ()) {
247+ g2pLog.srtWarning (" Manager::initialize: Phase 2 context=%1 no modules" , ctxKey.context );
213248 impl.m_contextStates [ctxKey] = ContextState::Failed;
214249 continue ;
215250 }
216251
217252 auto compatibleModules = filterCompatibleModules (moduleInfos);
218253 if (compatibleModules.empty ()) {
254+ g2pLog.srtWarning (" Manager::initialize: Phase 2 context=%1 no compatible modules" , ctxKey.context );
219255 impl.m_contextStates [ctxKey] = ContextState::Failed;
220256 continue ;
221257 }
@@ -226,26 +262,41 @@ namespace srt::g2p {
226262 depGraph.addModule (info);
227263
228264 if (!depGraph.buildGraph ()) {
265+ g2pLog.srtWarning (" Manager::initialize: Phase 2 context=%1 buildGraph failed" , ctxKey.context );
229266 impl.m_contextStates [ctxKey] = ContextState::Failed;
230267 continue ;
231268 }
232269
233270 if (const auto cycles = depGraph.findCycles (); !cycles.empty ()) {
271+ g2pLog.srtWarning (" Manager::initialize: Phase 2 context=%1 cycles detected" , ctxKey.context );
234272 impl.m_contextStates [ctxKey] = ContextState::Failed;
235273 continue ;
236274 }
237275
238276 auto packageOrder = depGraph.getPackageInitializationOrder ();
277+ g2pLog.srtInfo (" Manager::initialize: Phase 2 context=%1 packageOrder size=%2" ,
278+ ctxKey.context , packageOrder.size ());
239279 bool allFailed = true ;
240280 for (const auto &packageInfo : packageOrder) {
281+ g2pLog.srtInfo (" Manager::initialize: Phase 2 opening package=%1 path=%2" ,
282+ packageInfo.packageId ,
283+ stdc::path::to_utf8 (packageInfo.packagePath ));
241284 auto exp = this ->open (packageInfo.packagePath );
242- if (!exp)
285+ if (!exp) {
286+ g2pLog.srtWarning (" Manager::initialize: Phase 2 open FAILED package=%1: %2" ,
287+ packageInfo.packageId , exp.error ().message ());
243288 continue ;
289+ }
244290
245291 Package pkg = exp.take ();
246- if (!pkg.isLoaded ())
292+ if (!pkg.isLoaded ()) {
293+ g2pLog.srtWarning (" Manager::initialize: Phase 2 pkg not loaded package=%1: %2" ,
294+ packageInfo.packageId , pkg.error ().message ());
247295 continue ;
296+ }
248297
298+ g2pLog.srtInfo (" Manager::initialize: Phase 2 package=%1 loaded, creating %2 tasks" ,
299+ packageInfo.packageId , packageInfo.initializationOrder .size ());
249300 allFailed = false ;
250301 for (const auto &moduleInfo : packageInfo.initializationOrder ) {
251302 auto taskExp = createModuleTask (moduleInfo, pkg);
@@ -266,21 +317,29 @@ namespace srt::g2p {
266317 impl.m_contextStates [ctxKey] = ContextState::Failed;
267318 } else {
268319 impl.m_contextStates [ctxKey] = ContextState::Ready;
320+ g2pLog.srtInfo (" Manager::initialize: Phase 2 context=%1 Ready" , ctxKey.context );
269321 }
270322 }
323+ g2pLog.srtInfo (" Manager::initialize: Phase 2 END" );
271324
272325 // Phase 3: Load tasks for categories
326+ g2pLog.srtInfo (" Manager::initialize: Phase 3 (loadTasksForCategory g2p) START" );
273327 if (auto result = loadTasksForCategory (kG2pCategory ); !result) {
328+ g2pLog.srtWarning (" Manager::initialize: Phase 3 g2p FAILED: %1" , result.error ().message ());
274329 return std::move (result.takeError ()
275330 .withTrace (std::source_location::current (), " Manager::initialize" ));
276331 }
332+ g2pLog.srtInfo (" Manager::initialize: Phase 3 (loadTasksForCategory g2p) END" );
277333
334+ g2pLog.srtInfo (" Manager::initialize: Phase 3 (loadTasksForCategory dict) START" );
278335 if (auto result = loadTasksForCategory (kDictCategory ); !result) {
279336 // dict is optional - log warning but continue initialization
280337 g2pLog.srtWarning (" Dict task init failed - %1" , result.error ().message ());
281338 }
339+ g2pLog.srtInfo (" Manager::initialize: Phase 3 (loadTasksForCategory dict) END" );
282340
283341 impl.m_initialized = true ;
342+ g2pLog.srtInfo (" Manager::initialize: COMPLETE (m_initialized=true)" );
284343 return {};
285344 }
286345
0 commit comments