Bad script design or bug?


#1

Since people have been posting script stuff today and gotten some good replies (and @ZappoMan made me realize I suck at JS) , here is something I’ve run into with a script I’ve been trying to use. It is really two scripts.

One is an entity script that looks to see if a particular script is running on an avatar when the avatar approaches the entity on a domain. If the script is not running, the entity script then loads two scripts on the avatar. One being the desired script (in this case @ctrlaltdavid’s chat script). The other being a control script that does nothing but kills itself and the chat script when the avatar leaves the domain.

I did this with two scripts because I wanted to be able to load unmodified scripts hosted and maintained by others, rather than have to patch in code, maintain and host every script I wanted present on a domain.

The entity script looks like this:

// entity-chat-adder.js
// Function that adds a text chat UI script to a users screen (and a script to delete
// the chat script on leaving the domain) when the avatar nears the
// entity that contains this script.

(function() {
     const CHAT_NAME = “https://s3-us-west-1.amazonaws.com/hifiscripts/chat-control.js”;
    const SCRIPT_NAME = “http://ctrlaltstudio.com/downloads/hifi/scripts/chat.js”;
     function isScriptRunning(script) {
        script = script.toLowerCase().trim();
        var runningScripts = ScriptDiscoveryService.getRunning();
        for (i in runningScripts) {
            if (runningScripts[i].url.toLowerCase().trim() == script) {
                return true;
            }
        }
        return false;
    };
    
    if (!isScriptRunning(CHAT_NAME)) {
         Script.load(CHAT_NAME);
        Script.load(SCRIPT_NAME);
    }
})

The control script looks like this:

// chat-control.js
// Chat UI control script.

// Check if avatar has left the domain.
Window.domainChanged.connect(function() {
    onScriptEnding();
    Script.stop();
});

// Stop chat script upon exit.
function onScriptEnding() {
    const SCRIPT_NAME = “http://ctrlaltstudio.com/downloads/hifi/scripts/chat.js”;
    var script = SCRIPT_NAME;
    script = script.toLowerCase().trim();
    var runningScripts = ScriptDiscoveryService.getRunning();
    for (i in runningScripts) {
        if (runningScripts[i].url.toLowerCase().trim() == script) {
            ScriptDiscoveryService.stopScript(SCRIPT_NAME);
            }
        }
}

// Delete the chat script when a user leaves the domain.
Window.domainChanged.connect(function() {
    onScriptEnding();
    Script.stop();
});

// Call onScriptEnding function when script ends.
Script.scriptEnding.connect(onScriptEnding);

As some of you can probably tell, parts of this were adapted from @KevinThomas, @Thoys and @Konstantin’s zone audio stream script and most of the time this chat script loader works fine.

But every once in awhile (possibly when many things are loading or laggy), instead of one chat.js and one chat-control.js I end up with two copies of each: chat.js and chat(2).js etc.

This might not be much of a problem except that, If I go to running scripts and manually delete the two copies, Interface crashes and possibly crashes when I just leave the domain.

The problem is most likely in the script or design but I don’t understand why Interface crashes.


#2

… sounds like you might need to “debounce” your detection/loading logic if the adder script can be called multiple times ahead of ScriptDiscoveryService becoming aware of the chat script.

An easy thing to try is sleeping on the initial assumption for a moment and then repeating the check before doing the actual load:

    if (!isScriptRunning(CHAT_NAME)) {
      Script.setTimeout(function() {
	if (!isScriptRunning(CHAT_NAME)) {
           print("LOADING CHAT SCRIPTS");
           Script.load(CHAT_NAME); 
           Script.load(SCRIPT_NAME);
        } else print("CHAT SCRIPTS ALREADY LOADED");
      }, 1000);
    }

#3

Yes good point @humbletim. I was thinking it might be some kind of race condition and I might try debouncing but I am trying to get to the cause of why this is happening.

Part of my Interface log shows that two copies of each script were downloaded:

[11/22 11:07:36] [DEBUG] Finished loading: https://s3.amazonaws.com/hifi-public/models/props/chess/Bishop_White.fbx
[11/22 11:07:46] [DEBUG] New interval  66
[11/22 11:08:33] [DEBUG] New interval  1
[11/22 11:10:08] [DEBUG] Already downloading script at: “https://s3-us-west-1.amazonaws.com/hifiscripts/entity-chat-adder.js
[11/22 11:10:09] [DEBUG] Done downloading script at: “https://s3-us-west-1.amazonaws.com/hifiscripts/entity-chat-adder.js
[11/22 11:10:09] [DEBUG] Already downloading script at: “https://s3-us-west-1.amazonaws.com/hifiscripts/chat-control.js
[11/22 11:10:09] [DEBUG] Already downloading script at: “http://ctrlaltstudio.com/downloads/hifi/scripts/chat.js
[11/22 11:10:09] [DEBUG] Done downloading script at: “https://s3-us-west-1.amazonaws.com/hifiscripts/chat-control.js
[11/22 11:10:09] [DEBUG] Done downloading script at: “http://ctrlaltstudio.com/downloads/hifi/scripts/chat.js
[11/22 11:10:09] [DEBUG] Logging activity “loaded_script”
[11/22 11:10:09] [DEBUG] Logging activity “loaded_script”
[11/22 11:10:09] [DEBUG] Logging activity “loaded_script”
[11/22 11:10:09] [DEBUG] Logging activity “loaded_script”
[11/22 11:10:10] [WARNING] Setting::Manager::registerHandle(): Key registered more than once, overriding:  “Chat Window Size”

It made me think that maybe I had inadvertently copied the “chat-adder-entity.js” entity by accident (blatant plug for getting rid of Alt-drag = copy behavior). But I looked and as far as I can see, there is only one entity that has the script in it.

And besides, this would be really crappy if every time you ran an AC script you had to check if it had already been run.

But when testing, I crashed everything including Stack Manager. When starting it back up I ran into the issue that @Balpien​_​​Hammere was talking about on another post here: two of the download manager updates never finished. So I ended the still running AC processes and it still would not update. Then looked at processes running and saw domain server process still running, so I ended that too.

That fixed the update problem and when I went back to the domain, I did not get the multiple script copies error.

So, long story short: is it possible that multiple ACs could be the cause of my original problem? In the past I seem to remember that the Stack Manager would spawn new ACs when they had crashed, or maybe it is just an issue of AC processes that were not shut down correctly affecting the newly started domain.

Up to now I don’t check to see if everything has shut down correctly when restarting my domains. Some are on separate machines that I remote connect to, and have run mostly without problems for months.

Anyway, I am not sure that multiple “zombie” ACs are the problem but just giving an update on what I’ve noticed.


#4

An update on what I’ve found.

I think I may have found my problem with scripts loading more than once. While testing, I noticed that the error would appear after one of my domains would crash. I usually run two from this IP, one on a tiny server, the other local on the machine Interface runs on.

The one on the tiny server was setup more than a year ago, before there was automatic network setup. At the time I set it to run manually at the default port settings which it still does now. The local host domain I setup with full automatic network setup. Which works fine… most of the time as long as I start the manually setup one first.

I think the problem may be that when one or more of the domains crash, and does not shut down all AC’s correctly, then when I start up the local one, the auto network setup chooses the default port settings which were used by the crashed domain and I get multiple entity servers at the same IP and port.

I might change the port settings on the manually setup domain to see if that fixes it but I am wondering if I even should mix auto and manual networking on the same IP.

And I still don’t understand why I once got this problem Where a couple of the default scripts loaded multiple times.