Is there a way to drop into the debugger when any panic occurs like if there were a breakpoint?
I'm using Carbide.c++ 2.3.0. I know about the Debug Configurations > x86 Exceptions, but it covers only a small fraction of what can actually happen in a real application. For instance, it does not trap user panics, or ALLOC panics when application exits with memory leaks.
If you are using the emulator, you can debug panics by enabling 'just-in-time debugging. This is done by adding the following line to epoc32\data\epoc.ini:
JustInTime debug
For more details, see the epoc.ini reference in the SDK documentation.
To the best of my knowledge it can't be done.
What I've done is use simple function tracing logic so when a panic happens I have a stack trace at the point of the panic in my the panic handling code (which I log out). This works well except for the fact that you have to remember to add your macro's at the beginning of every function.
e.g.
#ifndef NDEBUG
class __FTrace
{
__FTrace(const char* function)
{
TraceManager::GetInstance().EnterFunction(function);
}
~__FTrace()
{
TraceManager::GetInstance().LeaveFunction(function);
}
};
#define FTRACE() __FTrace(__PRETTY_FUNCTION__)
#else
#define FTRACE()
#endif
void Func()
{
FTRACE();
...
}
For ALLOC's, I've had a lot of success with the Hook Logger under the emulator. It's a real pain to setup and use but it will make it real easy to track down ALLOC memory leaks.
UPDATE: As requested, here is what my panic handling code looks like. Note that my application has to run in the background all the time, so it's setup to restart the app when something bad happens. Also this code works for 3rd Edition SDK's, I haven't tried it on later versions of the SDK's.
The point is to run the main application in another thread and then wait for it to exit. Then check to see why the thread exits, it the thread as exited for unknown reasons, log stuff like my own stack trace and restart the application.
TInt StartMainThread(TAny*)
{
FTRACE();
__LOGSTR_TOFILE("Main Thread Start");
TInt result(KErrNone);
TRAPD(err, result = EikStart::RunApplication(NewApplication));
if(KErrNone != err || KErrNone != result )
{
__LOGSTR_TOFILE("EikStart::RunApplication error: trap(%d), %d", err, result);
}
__LOGSTR_TOFILE("Main Thread End");
return result;
}
const TInt KMainThreadToLiveInSeconds = 10;
} // namespace *unnamed*
LOCAL_C CApaApplication* NewApplication()
{
FTRACE();
return new CMainApplication;
}
GLDEF_C TInt E32Main()
{
#ifdef NDEBUG
__LOGSTR_TOFILE("Application Start (release)");
#else
__LOGSTR_TOFILE("Application Start (debug)");
#endif
#ifndef NO_TRACING
__TraceManager::NewL();
#endif // !NO_TRACING
RHeap& heap(User::Heap());
TInt heapsize=heap.MaxLength();
TInt exitReason(KErrNone);
TTime timeToLive;
timeToLive.UniversalTime();
timeToLive += TTimeIntervalSeconds(KMainThreadToLiveInSeconds);
LManagedHandle<RThread> mainThread;
TInt err = mainThread->Create(_L("Main Thread"), StartMainThread, KDefaultStackSize, KMinHeapSize, heapsize, NULL);
if (KErrNone != err)
{
__LOGSTR_TOFILE("MainThread failed : %d", err);
return err;
}
mainThread->SetPriority(EPriorityNormal);
TRequestStatus status;
mainThread->Logon(status);
mainThread->Resume();
User::WaitForRequest(status);
exitReason = mainThread->ExitReason();
TExitCategoryName category(mainThread->ExitCategory());
switch(mainThread->ExitType())
{
case EExitKill:
__LOGSTR_TOFILE("ExitKill : (%S) : %d", &category, exitReason);
break;
case EExitTerminate:
__LOGSTR_TOFILE("ExitTerminate : (%S) : %d", &category, exitReason);
break;
case EExitPanic:
__LOGSTR_TOFILE("ExitPanic : (%S) : %d", &category, exitReason);
break;
default:
__LOGSTR_TOFILE("ExitUnknown : (%S) : %d", &category, exitReason);
break;
}
#ifndef NO_TRACING
__TraceManager::GetInstance().LogStackTrace();
#endif // NO_TRACING
if( KErrNone != status.Int() )
{
TTime now;
now.UniversalTime();
if (timeToLive > now)
{
TTimeIntervalMicroSeconds diff = timeToLive.MicroSecondsFrom(now);
__LOGSTR_TOFILE("Exiting due to TTL : (%Lu)", diff.Int64());
}
else
{
RProcess current;
RProcess restart;
err = restart.Create(current.FileName(), _L(""));
if( KErrNone == err )
{
__LOGSTR_TOFILE("Restarting...");
restart.Resume();
return KErrNone;
}
else
{
__LOGSTR_TOFILE("Failed to start app: %d", err);
}
}
}
__LOGSTR_TOFILE("Application End");
return exitReason;
}
Related
I am programming the windows base application using MFC. when I was trying to use ON_CONTROL_RANGE function there is an error message popped up.
Visual Studio was used to build the app.
error
E0171 invalid type conversion
why is this error comes up,
give me a hint
Code
#define IDC_USR_MANUAL_TUNING_CH1_CHECK 1134
#define IDC_USR_MANUAL_TUNING_CH7_CHECK 1140
ON_CONTROL_RANGE(BN_CLICKED, IDC_USR_MANUAL_TUNING_CH1_CHECK, IDC_USR_MANUAL_TUNING_CH8_CHECK, OnUsrManualTuningChCheck)
void CMainteManualTuningDialog::OnUsrManualTuningChCheck(int nId)
{
if (FALSE == m_bInitFlag) // Initialization flag TRUE: Initialized / FALSE: Uninitialized
{
return;
}
UpdateData(TRUE);
int nChCnt = nId - IDC_USR_MANUAL_TUNING_CH1_CHECK;
if ((CH1 > nChCnt) || (CH8 < nChCnt))
{
return;
}
// unused
if (FALSE == m_bUseCheck[nChCnt])
{
if (nChCnt == m_rbutCh)
{
MessageBox("While selecting a channel, it cannot be invalidated.");
m_bUseCheck[nChCnt] = TRUE; // invalid
}
else
{
m_butUseCheck[nChCnt].SetWindowText(MSG_IGNORE); // Ignore
m_butChSel[nChCnt].EnableWindow(FALSE); // invalid
g_eTuningStat[nChCnt] = E_TUNING_STAT_NONE; // unused
m_strStatCh[nChCnt] = MSG_NONE; // unused
if (FALSE == m_clp->ZeroSetSend(nChCnt, m_pcTuningData))
{
((CMicroDetectorView*)m_hpView)->PostMessage(WM_USR_ALARM, eAPP_T);
}
}
}
// use
else
{
m_butUseCheck[nChCnt].SetWindowText(MSG_USE); // Use
m_butChSel[nChCnt].EnableWindow(TRUE); // Effectiveness
// Unadjusted the adjustment status
SetStatStill(nChCnt);
}
UpdateData(FALSE);
}
when we use the ON_CONTROL_RANGE(wNotifyCode, id, idLast, memberFxn)
memberFxn Fn has to use UINT variables
I've been trying to use and understand the DirectoryWatcher class from Microsoft's Cloud Mirror sample. It uses ReadDirectoryChangesW to monitor changes to a directory. I don't think it's reporting all changes, to be honest. In any event, I had a question about the key part of the code, which is as follows:
concurrency::task<void> DirectoryWatcher::ReadChangesAsync()
{
auto token = _cancellationTokenSource.get_token();
return concurrency::create_task([this, token]
{
while (true)
{
DWORD returned;
winrt::check_bool(ReadDirectoryChangesW(
_dir.get(),
_notify.get(),
c_bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_ATTRIBUTES,
&returned,
&_overlapped,
nullptr));
DWORD transferred;
if (GetOverlappedResultEx(_dir.get(), &_overlapped, &transferred, 1000, FALSE))
{
std::list<std::wstring> result;
FILE_NOTIFY_INFORMATION* next = _notify.get();
while (next != nullptr)
{
std::wstring fullPath(_path);
fullPath.append(L"\\");
fullPath.append(std::wstring_view(next->FileName, next->FileNameLength / sizeof(wchar_t)));
result.push_back(fullPath);
if (next->NextEntryOffset)
{
next = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(reinterpret_cast<char*>(next) + next->NextEntryOffset);
}
else
{
next = nullptr;
}
}
_callback(result);
}
else if (GetLastError() != WAIT_TIMEOUT)
{
throw winrt::hresult_error(HRESULT_FROM_WIN32(GetLastError()));
}
else if (token.is_canceled())
{
wprintf(L"watcher cancel received\n");
concurrency::cancel_current_task();
return;
}
}
}, token);
}
After reviewing an answer to another question, here's what I don't understand about the code above: isn't the code potentially re-calling ReadDirectoryChangesW before the prior call has returned a result? Or is this code indeed correct? Thanks for any input.
Yes, I seem to have confirmed in my testing that there should be another while loop there around the call to GetOverlappedResultEx, similar to the sample code provided in that other answer. I think the notifications are firing properly with it.
Shouldn't there also be a call to CancelIo in there, too? Or is that not necessary for some reason?
I am trying to stream audio data from disk using OpenAL's buffer queueing mechanism. I load and enqueue 4 buffers, start the source playing, and check in a regular intervals to refresh the queue. Everything looks like it's going splendidly, up until the first time I try to load data into a recycled buffer I got from alSourceUnqueueBuffers(). In this situation, alBufferData() always sets AL_INVALID_OPERATION, which according to the official v1.1 spec, it doesn't seem like it should be able to do.
I have searched extensively on Google and StackOverflow, and can't seem to find any reason why this would happen. The closest thing I found was someone with a possibly-related issue in an archived forum post, but details are few and responses are null. There was also this SO question with slightly different circumstances, but the only answer's suggestion does not help.
Possibly helpful: I know my context and device are configured correctly, because loading small wav files completely into a single buffer and playing them works fine. Through experimentation, I've also found that queueing 2 buffers, starting the source playing, and immediately loading and enqueueing the other two buffers throws no errors; it's only when I've unqueued a processed buffer that I run into trouble.
The relevant code:
static constexpr int MAX_BUFFER_COUNT = 4;
#define alCall(funcCall) {funcCall; SoundyOutport::CheckError(__FILE__, __LINE__, #funcCall) ? abort() : ((void)0); }
bool SoundyOutport::CheckError(const string &pFile, int pLine, const string &pfunc)
{
ALenum tErrCode = alGetError();
if(tErrCode != 0)
{
auto tMsg = alGetString(tErrCode);
Log::e(ro::TAG) << tMsg << " at " << pFile << "(" << pLine << "):\n"
<< "\tAL call " << pfunc << " failed." << end;
return true;
}
return false;
}
void SoundyOutport::EnqueueBuffer(const float* pData, int pFrames)
{
static int called = 0;
++called;
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
if(tState == AL_STATIC)
{
Stop();
// alCall(alSourcei(mSourceId, AL_BUFFER, NULL));
}
ALuint tBufId = AL_NONE;
int tQueuedBuffers = QueuedUpBuffers();
int tReady = ProcessedBuffers();
if(tQueuedBuffers < MAX_BUFFER_COUNT)
{
tBufId = mBufferIds[tQueuedBuffers];
}
else if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}
void* tConverted = convert(pData, pFrames);
// the fifth time through, we get AL_INVALID_OPERATION, and call abort()
alCall(alBufferData(tBufId, mFormat, tConverted, pFrames * mBitdepth/8, mSampleRate));
alCall(alSourceQueueBuffers(mSourceId, 1, &mBufferId));
if(mBitdepth == BITDEPTH_8)
{
delete (uint8_t*)tConverted;
}
else // if(mBitdepth == BITDEPTH_16)
{
delete (uint16_t*)tConverted;
}
}
void SoundyOutport::PlayBufferedStream()
{
if(!StreamingMode() || !QueuedUpBuffers())
{
Log::w(ro::TAG) << "Attempted to play an unbuffered stream" << end;
return;
}
alCall(alSourcei(mSourceId, AL_LOOPING, AL_FALSE)); // never loop streams
alCall(alSourcePlay(mSourceId));
}
int SoundyOutport::QueuedUpBuffers()
{
int tCount = 0;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_QUEUED, &tCount));
return tCount;
}
int SoundyOutport::ProcessedBuffers()
{
int tCount = 0;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_PROCESSED, &tCount));
return tCount;
}
void SoundyOutport::Stop()
{
if(Playing())
{
alCall(alSourceStop(mSourceId));
}
int tBuffers;
alCall(alGetSourcei(mSourceId, AL_BUFFERS_QUEUED, &tBuffers));
if(tBuffers)
{
ALuint tDummy[tBuffers];
alCall(alSourceUnqueueBuffers(mSourceId, tBuffers, tDummy));
}
alCall(alSourcei(mSourceId, AL_BUFFER, AL_NONE));
}
bool SoundyOutport::Playing()
{
ALint tPlaying;
alCall(alGetSourcei(mSourceId, AL_SOURCE_STATE, &tPlaying));
return tPlaying == AL_PLAYING;
}
bool SoundyOutport::StreamingMode()
{
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
return tState == AL_STREAMING;
}
bool SoundyOutport::StaticMode()
{
ALint tState;
alCall(alGetSourcei(mSourceId, AL_SOURCE_TYPE, &tState));
return tState == AL_STATIC;
}
And here's an annotated screen cap of what I see in my debugger when I hit the error:
I've tried a bunch of little tweaks and variations, and the result is always the same. I've wasted too many days trying to fix this. Please help :)
This error occurs when you trying to fill buffer with data, when the buffer is still queued to the source.
Also this code is wrong.
if(tQueuedBuffers < MAX_BUFFER_COUNT)
{
tBufId = mBufferIds[tQueuedBuffers];
}
else if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}
You can fill buffer with data only if it unqueued from source. But your first if block gets tBufId that queued to the source. Rewrite code like so
if(tReady > 0)
{
// the fifth time through, this code gets hit
alCall(alSourceUnqueueBuffers(mSourceId, 1, &tBufId));
// debug code: make sure these values go down by one
tQueuedBuffers = QueuedUpBuffers();
tReady = ProcessedBuffers();
}
else
{
return; // no update needed yet.
}
I started learning some basics about OpenCL a while ago and decided to give the "Basic programming sample" from Apple a go. I runs OK on CPU, but when I select GPU as the target device I get err = -45 from
err = gclExecKernelAPPLE(k, ndrange, &kargs);
This error code translates to CL_INVALID_PROGRAM_EXECUTABLE. Any idea how can I correct the sample code?
Automatically generated kernel.cl.c code looks like this (+ includes on top):
static void initBlocks(void);
// Initialize static data structures
static block_kernel_pair pair_map[1] = {
{ NULL, NULL }
};
static block_kernel_map bmap = { 0, 1, initBlocks, pair_map };
// Block function
void (^square_kernel)(const cl_ndrange *ndrange, cl_float* input, cl_float* output) =
^(const cl_ndrange *ndrange, cl_float* input, cl_float* output) {
int err = 0;
cl_kernel k = bmap.map[0].kernel;
if (!k) {
initBlocks();
k = bmap.map[0].kernel;
}
if (!k)
gcl_log_fatal("kernel square does not exist for device");
kargs_struct kargs;
gclCreateArgsAPPLE(k, &kargs);
err |= gclSetKernelArgMemAPPLE(k, 0, input, &kargs);
err |= gclSetKernelArgMemAPPLE(k, 1, output, &kargs);
gcl_log_cl_fatal(err, "setting argument for square failed");
err = gclExecKernelAPPLE(k, ndrange, &kargs);
gcl_log_cl_fatal(err, "Executing square failed");
gclDeleteArgsAPPLE(k, &kargs);
};
// Initialization functions
static void initBlocks(void) {
const char* build_opts = " -cl-std=CL1.1";
static dispatch_once_t once;
dispatch_once(&once,
^{ int err = gclBuildProgramBinaryAPPLE("OpenCL/kernel.cl", "", &bmap, build_opts);
if (!err) {
assert(bmap.map[0].block_ptr == square_kernel && "mismatch block");
bmap.map[0].kernel = clCreateKernel(bmap.program, "square", &err);
}
});
}
__attribute__((constructor))
static void RegisterMap(void) {
gclRegisterBlockKernelMap(&bmap);
bmap.map[0].block_ptr = square_kernel;
}
I saw this same problem when running under 10.7.3, while a machine on 10.7.5 worked fine. I noticed the CVMCompiler process was crashing after each invocation of my app.
Inspecting the stack trace, I noticed it was crashing when trying to parse the bitcode for compilation into native code. Since the parsing of the bitcode failed failed, there was no resulting compiled program for gclExecKernelAPPLE() to execute, hence the error.
Try upgrading to 10.7.5, or indeed 10.8 and the problem should go away. (I just tested this and it does indeed fix the problem.)
I have been trying to call a pdk plugin from the mojo hybrid app and have also tried the same with enyo app. In both cases my pdk plugin is shown as , Interesting thing is in case of enyo, i received the plugin_ready response which is sent after the plugin registration is complete.
in the web-os site, they mentioned that it is the issue with pdk plugin that makes it look defunct.
but i could not find a method to resolve it.
This is how my plugin looks,
PDL_bool powerCall(PDL_JSParameters *params) {
runsine();
char *reply = "Done";
PDL_JSReply(params, reply);
return PDL_TRUE;
}
int main(){
int result = SDL_Init(SDL_INIT_VIDEO);
PDL_Init(0);
PDL_RegisterJSHandler("pawar", powerCall);
PDL_JSRegistrationComplete();
PDL_CallJS("ready", NULL, 0); // this is for enyo
PDL_Quit();
SDL_Quit();
return 0;
}
please suggest me how to solve this issue. i know its a very simple task and am frustrated that its taking this long.
Thanks
Shankar
In your plugin you should enter an event loop after you call the "ready" function, and before you call the PDL_Quit() and SDL_Quit(). Not having an event loop causes the plugin process to quit right away.
Here is an example based on the "simple" app that ships with the PDK:
int main(){
int result = SDL_Init(SDL_INIT_VIDEO);
PDL_Init(0);
PDL_RegisterJSHandler("pawar", powerCall);
PDL_JSRegistrationComplete();
PDL_CallJS("ready", NULL, 0); // this is for enyo
atexit(SDL_Quit);
atexit(PDL_Quit);
SDL_Event Event;
bool paused = false;
while (1) {
bool gotEvent;
if (paused) {
SDL_WaitEvent(&Event);
gotEvent = true;
}
else {
gotEvent = SDL_PollEvent(&Event);
}
while (gotEvent) {
switch (Event.type) {
case SDL_ACTIVEEVENT:
if (Event.active.state == SDL_APPACTIVE) {
paused = !Event.active.gain;
}
break;
case SDL_QUIT:
// We exit anytime we get a request to quit the app
// all shutdown code is registered via atexit() so this is clean.
exit(0);
break;
// handle any other events interesting to your plugin here
default:
break;
}
gotEvent = SDL_PollEvent(&Event);
}
}
return 0;
}