bool DoExecute(Args &args, CommandReturnObject &result) override { if (args.empty()) { Log::ListAllLogChannels(&result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); } else { for (auto &entry : args.entries()) { Log::Callbacks log_callbacks; if (Log::GetLogChannelCallbacks(ConstString(entry.ref), log_callbacks)) { log_callbacks.list_categories(&result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); } else if (entry.ref == "all") { Log::ListAllLogChannels(&result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); } else { LogChannelSP log_channel_sp(LogChannel::FindPlugin(entry.c_str())); if (log_channel_sp) { log_channel_sp->ListCategories(&result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else result.AppendErrorWithFormat("Invalid log channel '%s'.\n", entry.c_str()); } } } return result.Succeeded(); }
bool DoExecute(Args &command, CommandReturnObject &result) override { if (!command.empty()) { result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str()); return false; } auto &r = repro::Reproducer::Instance(); if (auto generator = r.GetGenerator()) { generator->Keep(); } else if (r.GetLoader()) { // Make this operation a NOP in replay mode. result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } else { result.AppendErrorWithFormat("Unable to get the reproducer generator"); result.SetStatus(eReturnStatusFailed); return false; } result.GetOutputStream() << "Reproducer written to '" << r.GetReproducerPath() << "'\n"; result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); }
bool DoExecute(Args &args, CommandReturnObject &result) override { if (args.empty()) { result.AppendErrorWithFormat( "%s takes a log channel and one or more log types.\n", m_cmd_name.c_str()); return false; } Log::Callbacks log_callbacks; const std::string channel = args.GetArgumentAtIndex(0); args.Shift(); // Shift off the channel if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) { log_callbacks.disable(args.GetConstArgumentVector(), &result.GetErrorStream()); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else if (channel == "all") { Log::DisableAllLogChannels(&result.GetErrorStream()); } else { LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel.data())); if (log_channel_sp) { log_channel_sp->Disable(args.GetConstArgumentVector(), &result.GetErrorStream()); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else result.AppendErrorWithFormat("Invalid log channel '%s'.\n", channel.data()); } return result.Succeeded(); }
bool DoExecute(Args &command, CommandReturnObject &result) override { if (!command.empty()) { result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str()); return false; } auto &r = repro::Reproducer::Instance(); if (r.GetGenerator()) { result.GetOutputStream() << "Reproducer is in capture mode.\n"; } else if (r.GetLoader()) { result.GetOutputStream() << "Reproducer is in replay mode.\n"; } else { result.GetOutputStream() << "Reproducer is off.\n"; } result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); }
bool CommandObjectArgs::DoExecute(Args &args, CommandReturnObject &result) { ConstString target_triple; Process *process = m_exe_ctx.GetProcessPtr(); if (!process) { result.AppendError("Args found no process."); result.SetStatus(eReturnStatusFailed); return false; } const ABI *abi = process->GetABI().get(); if (!abi) { result.AppendError("The current process has no ABI."); result.SetStatus(eReturnStatusFailed); return false; } if (args.empty()) { result.AppendError("args requires at least one argument"); result.SetStatus(eReturnStatusFailed); return false; } Thread *thread = m_exe_ctx.GetThreadPtr(); if (!thread) { result.AppendError("args found no thread."); result.SetStatus(eReturnStatusFailed); return false; } lldb::StackFrameSP thread_cur_frame = thread->GetSelectedFrame(); if (!thread_cur_frame) { result.AppendError("The current thread has no current frame."); result.SetStatus(eReturnStatusFailed); return false; } ModuleSP thread_module_sp( thread_cur_frame->GetFrameCodeAddress().GetModule()); if (!thread_module_sp) { result.AppendError("The PC has no associated module."); result.SetStatus(eReturnStatusFailed); return false; } TypeSystem *type_system = thread_module_sp->GetTypeSystemForLanguage(eLanguageTypeC); if (type_system == nullptr) { result.AppendError("Unable to create C type system."); result.SetStatus(eReturnStatusFailed); return false; } ValueList value_list; for (auto &arg_entry : args.entries()) { llvm::StringRef arg_type = arg_entry.ref; Value value; value.SetValueType(Value::eValueTypeScalar); CompilerType compiler_type; std::size_t int_pos = arg_type.find("int"); if (int_pos != llvm::StringRef::npos) { Encoding encoding = eEncodingSint; int width = 0; if (int_pos > 1) { result.AppendErrorWithFormat("Invalid format: %s.\n", arg_entry.c_str()); result.SetStatus(eReturnStatusFailed); return false; } if (int_pos == 1 && arg_type[0] != 'u') { result.AppendErrorWithFormat("Invalid format: %s.\n", arg_entry.c_str()); result.SetStatus(eReturnStatusFailed); return false; } if (arg_type[0] == 'u') { encoding = eEncodingUint; } llvm::StringRef width_spec = arg_type.drop_front(int_pos + 3); auto exp_result = llvm::StringSwitch<llvm::Optional<int>>(width_spec) .Case("8_t", 8) .Case("16_t", 16) .Case("32_t", 32) .Case("64_t", 64) .Default(llvm::None); if (!exp_result.hasValue()) { result.AppendErrorWithFormat("Invalid format: %s.\n", arg_entry.c_str()); result.SetStatus(eReturnStatusFailed); return false; } width = *exp_result; compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize(encoding, width); if (!compiler_type.IsValid()) { result.AppendErrorWithFormat( "Couldn't get Clang type for format %s (%s integer, width %d).\n", arg_entry.c_str(), (encoding == eEncodingSint ? "signed" : "unsigned"), width); result.SetStatus(eReturnStatusFailed); return false; } } else if (arg_type == "void*") { compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); } else if (arg_type == "char*") { compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeChar).GetPointerType(); } else { result.AppendErrorWithFormat("Invalid format: %s.\n", arg_entry.c_str()); result.SetStatus(eReturnStatusFailed); return false; } value.SetCompilerType(compiler_type); value_list.PushValue(value); } if (!abi->GetArgumentValues(*thread, value_list)) { result.AppendError("Couldn't get argument values"); result.SetStatus(eReturnStatusFailed); return false; } result.GetOutputStream().Printf("Arguments : \n"); for (auto entry : llvm::enumerate(args.entries())) { result.GetOutputStream().Printf("%" PRIu64 " (%s): ", (uint64_t)entry.Index, entry.Value.c_str()); value_list.GetValueAtIndex(entry.Index)->Dump(&result.GetOutputStream()); result.GetOutputStream().Printf("\n"); } return result.Succeeded(); }
bool DoExecute(Args &command, CommandReturnObject &result) override { // No need to check "frame" for validity as eCommandRequiresFrame ensures it // is valid StackFrame *frame = m_exe_ctx.GetFramePtr(); Stream &s = result.GetOutputStream(); // Be careful about the stack frame, if any summary formatter runs code, it // might clear the StackFrameList // for the thread. So hold onto a shared pointer to the frame so it stays // alive. VariableList *variable_list = frame->GetVariableList(m_option_variable.show_globals); VariableSP var_sp; ValueObjectSP valobj_sp; const char *name_cstr = nullptr; size_t idx; TypeSummaryImplSP summary_format_sp; if (!m_option_variable.summary.IsCurrentValueEmpty()) DataVisualization::NamedSummaryFormats::GetSummaryFormat( ConstString(m_option_variable.summary.GetCurrentValue()), summary_format_sp); else if (!m_option_variable.summary_string.IsCurrentValueEmpty()) summary_format_sp.reset(new StringSummaryFormat( TypeSummaryImpl::Flags(), m_option_variable.summary_string.GetCurrentValue())); DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault, summary_format_sp)); const SymbolContext &sym_ctx = frame->GetSymbolContext(eSymbolContextFunction); if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction()) m_option_variable.show_globals = true; if (variable_list) { const Format format = m_option_format.GetFormat(); options.SetFormat(format); if (!command.empty()) { VariableList regex_var_list; // If we have any args to the variable command, we will make // variable objects from them... for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != nullptr; ++idx) { if (m_option_variable.use_regex) { const size_t regex_start_index = regex_var_list.GetSize(); llvm::StringRef name_str(name_cstr); RegularExpression regex(name_str); if (regex.Compile(name_str)) { size_t num_matches = 0; const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, regex_var_list, num_matches); if (num_new_regex_vars > 0) { for (size_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize(); regex_idx < end_index; ++regex_idx) { var_sp = regex_var_list.GetVariableAtIndex(regex_idx); if (var_sp) { valobj_sp = frame->GetValueObjectForFrameVariable( var_sp, m_varobj_options.use_dynamic); if (valobj_sp) { // if (format // != // eFormatDefault) // valobj_sp->SetFormat // (format); std::string scope_string; if (m_option_variable.show_scope) scope_string = GetScopeString(var_sp).str(); if (!scope_string.empty()) s.PutCString(scope_string); if (m_option_variable.show_decl && var_sp->GetDeclaration().GetFile()) { bool show_fullpaths = false; bool show_module = true; if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) s.PutCString(": "); } valobj_sp->Dump(result.GetOutputStream(), options); } } } } else if (num_matches == 0) { result.GetErrorStream().Printf("error: no variables matched " "the regular expression '%s'.\n", name_cstr); } } else { char regex_error[1024]; if (regex.GetErrorAsCString(regex_error, sizeof(regex_error))) result.GetErrorStream().Printf("error: %s\n", regex_error); else result.GetErrorStream().Printf( "error: unknown regex error when compiling '%s'\n", name_cstr); } } else // No regex, either exact variable names or variable // expressions. { Error error; uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsAllowDirectIVarAccess | StackFrame::eExpressionPathOptionsInspectAnonymousUnions; lldb::VariableSP var_sp; valobj_sp = frame->GetValueForVariableExpressionPath( name_cstr, m_varobj_options.use_dynamic, expr_path_options, var_sp, error); if (valobj_sp) { std::string scope_string; if (m_option_variable.show_scope) scope_string = GetScopeString(var_sp).str(); if (!scope_string.empty()) s.PutCString(scope_string); // if (format != eFormatDefault) // valobj_sp->SetFormat (format); if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration().GetFile()) { var_sp->GetDeclaration().DumpStopContext(&s, false); s.PutCString(": "); } options.SetFormat(format); options.SetVariableFormatDisplayLanguage( valobj_sp->GetPreferredDisplayLanguage()); Stream &output_stream = result.GetOutputStream(); options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : nullptr); valobj_sp->Dump(output_stream, options); } else { const char *error_cstr = error.AsCString(nullptr); if (error_cstr) result.GetErrorStream().Printf("error: %s\n", error_cstr); else result.GetErrorStream().Printf("error: unable to find any " "variable expression path that " "matches '%s'.\n", name_cstr); } } } } else // No command arg specified. Use variable_list, instead. { const size_t num_variables = variable_list->GetSize(); if (num_variables > 0) { for (size_t i = 0; i < num_variables; i++) { var_sp = variable_list->GetVariableAtIndex(i); bool dump_variable = true; std::string scope_string; if (dump_variable && m_option_variable.show_scope) scope_string = GetScopeString(var_sp).str(); if (dump_variable) { // Use the variable object code to make sure we are // using the same APIs as the public API will be // using... valobj_sp = frame->GetValueObjectForFrameVariable( var_sp, m_varobj_options.use_dynamic); if (valobj_sp) { // if (format != eFormatDefault) // valobj_sp->SetFormat // (format); // When dumping all variables, don't print any variables // that are not in scope to avoid extra unneeded output if (valobj_sp->IsInScope()) { if (!valobj_sp->GetTargetSP() ->GetDisplayRuntimeSupportValues() && valobj_sp->IsRuntimeSupportValue()) continue; if (!scope_string.empty()) s.PutCString(scope_string); if (m_option_variable.show_decl && var_sp->GetDeclaration().GetFile()) { var_sp->GetDeclaration().DumpStopContext(&s, false); s.PutCString(": "); } options.SetFormat(format); options.SetVariableFormatDisplayLanguage( valobj_sp->GetPreferredDisplayLanguage()); options.SetRootValueObjectName(name_cstr); valobj_sp->Dump(result.GetOutputStream(), options); } } } } } } result.SetStatus(eReturnStatusSuccessFinishResult); } if (m_interpreter.TruncationWarningNecessary()) { result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(), m_cmd_name.c_str()); m_interpreter.TruncationWarningGiven(); } return result.Succeeded(); }
bool CommandObjectDisassemble::DoExecute(Args &command, CommandReturnObject &result) { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == nullptr) { result.AppendError("invalid target, create a debug target using the " "'target create' command"); result.SetStatus(eReturnStatusFailed); return false; } if (!m_options.arch.IsValid()) m_options.arch = target->GetArchitecture(); if (!m_options.arch.IsValid()) { result.AppendError( "use the --arch option or set the target architecture to disassemble"); result.SetStatus(eReturnStatusFailed); return false; } const char *plugin_name = m_options.GetPluginName(); const char *flavor_string = m_options.GetFlavorString(); DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name); if (!disassembler) { if (plugin_name) { result.AppendErrorWithFormat( "Unable to find Disassembler plug-in named '%s' that supports the " "'%s' architecture.\n", plugin_name, m_options.arch.GetArchitectureName()); } else result.AppendErrorWithFormat( "Unable to find Disassembler plug-in for the '%s' architecture.\n", m_options.arch.GetArchitectureName()); result.SetStatus(eReturnStatusFailed); return false; } else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec(m_options.arch, flavor_string)) result.AppendWarningWithFormat( "invalid disassembler flavor \"%s\", using default.\n", flavor_string); result.SetStatus(eReturnStatusSuccessFinishResult); if (!command.empty()) { result.AppendErrorWithFormat( "\"disassemble\" arguments are specified as options.\n"); const int terminal_width = GetCommandInterpreter().GetDebugger().GetTerminalWidth(); GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this, terminal_width); result.SetStatus(eReturnStatusFailed); return false; } if (m_options.show_mixed && m_options.num_lines_context == 0) m_options.num_lines_context = 2; // Always show the PC in the disassembly uint32_t options = Disassembler::eOptionMarkPCAddress; // Mark the source line for the current PC only if we are doing mixed source // and assembly if (m_options.show_mixed) options |= Disassembler::eOptionMarkPCSourceLine; if (m_options.show_bytes) options |= Disassembler::eOptionShowBytes; if (m_options.raw) options |= Disassembler::eOptionRawOuput; if (!m_options.func_name.empty()) { ConstString name(m_options.func_name.c_str()); if (Disassembler::Disassemble( m_interpreter.GetDebugger(), m_options.arch, plugin_name, flavor_string, m_exe_ctx, name, nullptr, // Module * m_options.num_instructions, m_options.show_mixed, m_options.show_mixed ? m_options.num_lines_context : 0, options, result.GetOutputStream())) { result.SetStatus(eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat("Unable to find symbol with name '%s'.\n", name.GetCString()); result.SetStatus(eReturnStatusFailed); } } else { std::vector<AddressRange> ranges; AddressRange range; StackFrame *frame = m_exe_ctx.GetFramePtr(); if (m_options.frame_line) { if (frame == nullptr) { result.AppendError("Cannot disassemble around the current line without " "a selected frame.\n"); result.SetStatus(eReturnStatusFailed); return false; } LineEntry pc_line_entry( frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); if (pc_line_entry.IsValid()) { range = pc_line_entry.range; } else { m_options.at_pc = true; // No line entry, so just disassemble around the current pc m_options.show_mixed = false; } } else if (m_options.current_function) { if (frame == nullptr) { result.AppendError("Cannot disassemble around the current function " "without a selected frame.\n"); result.SetStatus(eReturnStatusFailed); return false; } Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; if (symbol) { range.GetBaseAddress() = symbol->GetAddress(); range.SetByteSize(symbol->GetByteSize()); } } // Did the "m_options.frame_line" find a valid range already? If so // skip the rest... if (range.GetByteSize() == 0) { if (m_options.at_pc) { if (frame == nullptr) { result.AppendError("Cannot disassemble around the current PC without " "a selected frame.\n"); result.SetStatus(eReturnStatusFailed); return false; } range.GetBaseAddress() = frame->GetFrameCodeAddress(); if (m_options.num_instructions == 0) { // Disassembling at the PC always disassembles some number of // instructions (not the whole function). m_options.num_instructions = DEFAULT_DISASM_NUM_INS; } ranges.push_back(range); } else { range.GetBaseAddress().SetOffset(m_options.start_addr); if (range.GetBaseAddress().IsValid()) { if (m_options.end_addr != LLDB_INVALID_ADDRESS) { if (m_options.end_addr <= m_options.start_addr) { result.AppendErrorWithFormat( "End address before start address.\n"); result.SetStatus(eReturnStatusFailed); return false; } range.SetByteSize(m_options.end_addr - m_options.start_addr); } ranges.push_back(range); } else { if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS && target) { if (!target->GetSectionLoadList().IsEmpty()) { bool failed = false; Address symbol_containing_address; if (target->GetSectionLoadList().ResolveLoadAddress( m_options.symbol_containing_addr, symbol_containing_address)) { ModuleSP module_sp(symbol_containing_address.GetModule()); SymbolContext sc; bool resolve_tail_call_address = true; // PC can be one past the // address range of the // function. module_sp->ResolveSymbolContextForAddress( symbol_containing_address, eSymbolContextEverything, sc, resolve_tail_call_address); if (sc.function || sc.symbol) { sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range); } else { failed = true; } } else { failed = true; } if (failed) { result.AppendErrorWithFormat( "Could not find function bounds for address 0x%" PRIx64 "\n", m_options.symbol_containing_addr); result.SetStatus(eReturnStatusFailed); return false; } ranges.push_back(range); } else { for (lldb::ModuleSP module_sp : target->GetImages().Modules()) { lldb::addr_t file_addr = m_options.symbol_containing_addr; Address file_address; if (module_sp->ResolveFileAddress(file_addr, file_address)) { SymbolContext sc; bool resolve_tail_call_address = true; // PC can be one past // the address range of // the function. module_sp->ResolveSymbolContextForAddress( file_address, eSymbolContextEverything, sc, resolve_tail_call_address); if (sc.function || sc.symbol) { sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range); ranges.push_back(range); } } } } } } } } else ranges.push_back(range); if (m_options.num_instructions != 0) { if (ranges.empty()) { // The default action is to disassemble the current frame function. if (frame) { SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); if (sc.function) range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress(); else if (sc.symbol && sc.symbol->ValueIsAddress()) range.GetBaseAddress() = sc.symbol->GetAddress(); else range.GetBaseAddress() = frame->GetFrameCodeAddress(); } if (!range.GetBaseAddress().IsValid()) { result.AppendError("invalid frame"); result.SetStatus(eReturnStatusFailed); return false; } } bool print_sc_header = ranges.size() > 1; for (AddressRange cur_range : ranges) { if (Disassembler::Disassemble( m_interpreter.GetDebugger(), m_options.arch, plugin_name, flavor_string, m_exe_ctx, cur_range.GetBaseAddress(), m_options.num_instructions, m_options.show_mixed, m_options.show_mixed ? m_options.num_lines_context : 0, options, result.GetOutputStream())) { result.SetStatus(eReturnStatusSuccessFinishResult); } else { if (m_options.start_addr != LLDB_INVALID_ADDRESS) result.AppendErrorWithFormat( "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr); else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) result.AppendErrorWithFormat( "Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", m_options.symbol_containing_addr); result.SetStatus(eReturnStatusFailed); } } if (print_sc_header) result.AppendMessage("\n"); } else { if (ranges.empty()) { // The default action is to disassemble the current frame function. if (frame) { SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); if (sc.function) range = sc.function->GetAddressRange(); else if (sc.symbol && sc.symbol->ValueIsAddress()) { range.GetBaseAddress() = sc.symbol->GetAddress(); range.SetByteSize(sc.symbol->GetByteSize()); } else range.GetBaseAddress() = frame->GetFrameCodeAddress(); } else { result.AppendError("invalid frame"); result.SetStatus(eReturnStatusFailed); return false; } ranges.push_back(range); } bool print_sc_header = ranges.size() > 1; for (AddressRange cur_range : ranges) { if (cur_range.GetByteSize() == 0) cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); if (Disassembler::Disassemble( m_interpreter.GetDebugger(), m_options.arch, plugin_name, flavor_string, m_exe_ctx, cur_range, m_options.num_instructions, m_options.show_mixed, m_options.show_mixed ? m_options.num_lines_context : 0, options, result.GetOutputStream())) { result.SetStatus(eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat( "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr); result.SetStatus(eReturnStatusFailed); } if (print_sc_header) result.AppendMessage("\n"); } } } return result.Succeeded(); }
integer ServiceApp::startCommand(ConstStrA command, const Args & args, SeqFileOutput &serr) { if (command == ConstStrA(startCmd)) { integer x = validateService(args,serr); if (x) return x; createInstanceFile(); x = onMessage(command,args,serr); if (x) return x; x = initService(args,serr); if (x) return x; serr = nil; instance->enterDaemonMode(restartDelaySec); return startService(); } else if (command == ConstStrA(startForeCmd)) { integer x = validateService(args,serr); if (x) return x; createInstanceFile(); x = onMessage(command,args,serr); if (x) return x; x = initService(args,serr); if (x) return x; return startService(); } else if (command == ConstStrA(restartCmd)){ integer x = validateService(args,serr); if (x) return x; try { instance->open(); postMessage(stopCmd,Args(), serr); instance->waitForTerminate(timeout); } catch (ProgInstance::NotRunningException &) { } catch (ProgInstance::TimeoutException &) { instance->terminate(); instance->waitForTerminate(timeout); } createInstanceFile(); x = onMessage(command,args,serr); if (x) return x; x = initService(args,serr); if (x) return x; serr = nil; instance->enterDaemonMode(restartDelaySec); return startService(); } else if (command == ConstStrA(stopCmd)) { try { instance->open(); integer res = postMessage(command,args, serr); if (res == 0) instance->waitForTerminate(timeout); return res; } catch (ProgInstance::TimeoutException &) { instance->terminate(); return 0; } } else if (command == ConstStrA(waitCmd)) { natural timeout = naturalNull; if (!args.empty()) { TextParser<wchar_t> parser; if (parser(L" %u1 ",args[0])) timeout = parser[1]; } instance->open(); instance->waitForTerminate(timeout); } else if (command == ConstStrA(testCmd)) { integer x = validateService(args, serr); return x; } else if (command == ConstStrA(runTestsCmd)) { if (args.empty()) return Singleton<TestCollector>::getInstance().runTests(ConstStrA(), serr); else if (args[0] == ConstStrW(L"list")) { SeqTextOutA out(serr); TextOut<SeqTextOutA> print(out); print("%1\n")<<(Singleton<TestCollector>::getInstance().listTests()); return 0; } else return Singleton<TestCollector>::getInstance().runTests(args[1], serr); } else { instance->open(); return postMessage(command,args, serr); } return 0; }