Panorama X says open database is not open

Yes, I did try using zlog statements scattered throughout the offending proc, but I found that when PanX crashed, there was no info in the log - and yes it worked in the absence of crashes. I figured, maybe incorrectly, the the new debug system didn’t work when a crash occurred. Could the debug info have been buffered and never made it out the door?

I also downgraded PanX to b24 but that made no difference. I’m now back to b25.

If you are looking at the log file, then yes, that is definitely buffered and will not be complete if there is a crash.

In this situation, what you want to do is run Panorama X under Terminal.app. The log in Terminal.app is not buffered, and will be 100% complete right up to the point of a crash. The Debug Instrumentation page explains how to run Panorama X under Terminal.app. It’s quite easy, but does require a short setup process, and does require you to launch Panorama a special way each time.

Unless you’ve installed a case-sensitive file system on your Mac, you do not have two files with the same name. And you’d know if you had installed a case-sensitive file system.

Your screen shot shows that you have two windows named Tickers. That does not mean you have two files named Tickers. A form window can be renamed to anything you want – one of those could even be some other database.

FYI I’m not talking about a debugger. But you’ll see what it is when you watch the video.

I wasn’t suggesting that this would be permanent, just that it might indicate whether this was something that had changed in the b25 version. Apparently it isn’t, so this is a moot point.

Ok, now I’m guessing that this is originally Pierre’s database, and Pierre’s 900 line program, and you are helping him with it? That’s fine, of course, I’m just trying to understand the players. It’s been a bit confusing with both of you chiming in, but if this is actually Pierre’s database that makes a bit more sense.

I don’t understand your reference to a form window. None of the databases in question has any forms. And when I hit the F3 key, I definitely have two Panorama X databases with the Tickers name at the top. My thought was this would worry macOS.

Well, not exactly, it’s his program but I wrote it - he’s still on his trainer wheels. It’s part of a large project.

I shouldn’t have restricted it to form windows. Any window can be renamed to any name with the windowname statement. For example, here is a data sheet.

By running the code:

windowname "Fake Window Name"

I now have this window:

If I already had a database open with the name Fake Window Name, it would now appear that I have two data sheets open with that name.

I’m not saying that you necessarily are doing this, just pointing out that two windows with the same name doesn’t mean that two files have the same name.

F3 is Expose, correct? I don’t usually use the Fn keys, but it appears to be expose on my system.

So when you way you have two “databases”, I think you are meaning to say that you have two data sheets with the Tickers name. Assuming you didn’t use the windowname statement, this would probably mean that at some point Panorama got confused and allowed the same database to be opened twice in separate internal (in-memory) data structures. This is not supposed to ever happen – the first thing the open database code does is check to see if the database is already open. But for some reason this check isn’t finding a match.

I tried experimenting with the closedatabase and closefile statements to see if I could duplicate this problem, but I couldn’t get either of these to fail in this way (or fail at all). I did verify that the closedatabase statement works fine when used with the active database.

So I think something in your 900 lines of code is messing up the internal structure that Panorama uses to manage open databases.

You should be able to check the number of Tickers data sheet windows with this formula.

linecount(arraystrip(arrayfilter(info("windows"),cr(),{?(import() match "Tickers",import(),"")}),cr()))

You could create a mini-procedure at the end of your big procedure like this:

checkTickers:
    let tickerWindows = linecount(arraystrip(arrayfilter(info("windows"),cr(),{?(import() match "Tickers",import(),"")}),cr()))
    if tickerWindows > 1
        message "Extra ticker at "+parameter(1)
        stop
    endif
    return

Then, at various spots you could call the subtoutine this like this

shortcall checkTickers,"spot ABC"
...
shortcall checkTickers,"spot DEF"
...
shortcall checkTickers,"spot XYZ"

As soon as more than one Tickers window is detected, the procedure will stop and display a message indicating where the problem is. Whatever the problem is, it must be in the code above where the shortcall statement was. Since apparently Panorama’s internal memory structure is compromised, I would suggest quitting and relaunching Panorama after each time you run this test.

You can start with just a few shortcalls to this mini-procedure, then keep adding more as you learn what the target area is.

It’s possible (even probable) that the actual problem is caused before the duplicate window symptom appears. So this probably won’t find the exact line of the problem. But the problem is definitely not caused after the duplicate window shows up, so this should definitely narrow down the scope of the search for this problem.

My heartfelt thanks for the time you’re putting in on this. Of course, if the end result is the discovery of a big bad bug, it will all have been worth it.

On your final point,

I think you’re spot on. I’m now running a procedure which calls (as separate mini-procedures) just the first two modules of the big procedure. The second mini-procedure (.UpdateTickers3) runs successfully on its own but, when both are called in sequence, the second keeps failing at a lookup("Tickers" ... statement despite numerous amendments to the first, finally producing this gem:

Screen Shot 2022-01-30 at 4.59.28 pm

I’m taking a break from it today.

It seems like perhaps somehow you are winding up with a window that doesn’t actually have a Panorama database backing it. I have no idea how that could happen, but it seems like that could match the symptoms. Maybe somehow at some point the database is getting closed in memory but the window is not actually closed. Then if you open that file again you wind up with two windows.

You’re probably all fed up with this saga by now but this is really for Jim’s benefit.

I have now subdivided the large distribution procedure into 11 separate procedures. If I run the 11 procedures independently by choosing them from the Action menu one after the other they run perfectly. If I run a procedure which calls them in turn I get several intermittent and not always repeatable fails, almost always with a frozen database which has to be quit and then triggers a crash

All of my recent crashes (maybe 30 or more?) have been Apple-inspired after Panorama X freezes, mostly due to Panorama X’s inability to recognise an open database, and has to be manually quit.

The superalert statement with a timeout of one second can sit there forever unless I put a delay statement between it and a preceding closefile and sometimes it does it anyway.

The following is a common chain of events if all modules are run in sequence:

  1. Run the procedure which calls the modules in sequence with complete success. Quit and reopen manually.
  2. Run the procedure again and it freezes in Module 7. Quit and reopen manually.
  3. Run the procedure again and none of the superalert statements close - have to be closed manually. Quit and reopen manually.
  4. Run the procedure and it freezes in Module 2. Quit and reopen manually.
  5. Run the procedure and it can’t find procedure Module 9. Go and talk to my dog.

Screen Shot 2022-02-01 at 4.41.36 pm

Replacing superalert “End of Module 8”, {timeout=1} with message “End of Module 8” solves this problem (every module ends with a superalert so I know where it’s failed). There certainly appears to be a problem with the superalert statement.

The sequential call procedure is now running successfully three times out of four after inserting delay statements all over the place. That’s great progress compared with where I’ve been.

Oh, and a touch of deja vu - the old issue of save followed by closefile has re-emerged. I have to separate them with an nop.

The most helpful idea I have is the the dog is inserting some malicious code so you will come spend more time with him. But I can say, for the little that it may be worth, that I am very suspicious in these situations, and I have been in them, using alerts. My choice would be to us the logging system with zlog statements to monitor the progress of the procedures and possibly report errors.

1 Like

I really wish you would have tried this suggestion I made a few days ago. Based on some tests I just did, I think it would eliminate all of the problems in your code. Basically, if you close a database and then immediately open it again, the open doesn’t work.

This may be difficult or impossible to fix. The closefile and closedatabase statements work by telling Apple’s code to close the document. I believe the Apple code does this asynchronously, in other words, the Apple code returns control to Panorama immediately but the “close” operation continues in the background. For other asynchronous operations like saving and printing, Apple provides a mechanism to notify the original program when the task is finished. When running Panorama code, this notification mechanism allows Panorama to stop and wait for the task to finish before proceeding to the next statement. But there is no such notification mechanism for close. Apple seems to assume that they can take whatever amount of time they want in the background, and normally they would be correct.

For the tiny database I was using, I found that the problem went away if I used a wait 1 after the close operation. A delay of 0 wouldn’t work. But I think there is absolutely no assurance that 1 is enough for any database, it probably isn’t. I don’t think there is any way to know what a sufficient time is. I do not recommend putting wait statements after your close statements.

What does the doctor say when you tell him “it hurts when I do that”? He says don’t do that! You haven’t explicitly told us that you are closing a database and then turning around and opening it again, but you are doing that, right? I think the best solution is to not do that. At the start of your task, open the databases you need. Leave them all open until the task is complete. If for some reason you don’t want the windows visible, use makesecret. But don’t close them until the end.

1 Like

I believe that the only time I was doing that was when Module n would close all open databases and Module n+1 would open one or more of them again, with each module procedure called in turn.

The locations of the fails I experienced were highly varied and inconsistent with no guarantee of repeatability. With the procedure left open, the problematic code line was sometimes highlighted but most times the procedure just displayed its first page with no line highlighted, even though there was an error message in the dialog line at the bottom.

I have taken your doctor’s advice - I’m rebuilding the procedure (much reduced in size) module by module and thoroughly testing each one as I go. Like Frank Sinatra, I have high hopes.

And I’ll do that.

That would do it. The fact that the code is in different “modules” doesn’t mean anything to Panorama’s runtime engine, which simply runs each statement as fast as it can. So the first statement of module 2 will run just a few milliseconds after the last statement of module 1. The effect is pretty much the same as if the two statements were right next to each other in a single procedure.

I didn’t make that clear - Module n and Module n+1 are separate procedures. A master procedure calls each of them in turn so Module n has disappeared (or has it?) before Module n+1 is executed.

I guess I didn’t make it clear either. It makes no difference that they are separate procedures. Panorama just executes statements one after another. There is no significant delay in calling a separate procedure.

Module n has disappeared (or has it?)

No, it hasn’t disappeared. It’s still in memory. When you open a database, all of the procedures (and forms) are all brought into memory immediately, and they stay there until the database is closed.

Actually, when you call a procedure, Panorama makes a copy of that procedure in memory, so that if the database is closed while the procedure is running, the procedure can continue. It’s actually the copy that runs, not the original procedure. But making that copy only takes a few tens of microseconds.

I reckon I’ve learned more useful Panorama X peculiarities and tweaks in this topic than in the last couple of years.

I reassembled the procedure and, taking Jim’s advice, delayed all file closures until the end and it ran without a hitch.

1 Like