ServerBoot.add and thisProcess. nowExecutingPath

Hello,

Is there a specific reason why thisProcess. nowExecutingPath, thisProcess. nowExecutingPath.dirname, etc do not work with ServerBoot.add?
A code example can be found here:

You need to evaluate thisProcess.nowExecutingPath first, outside ServerBoot.add

(
var soundFolder = thisProcess.nowExecutingPath;// +/+ "BW2 Exports";
ServerBoot.add({
	Buffer.freeAll; // I am not sure if it is necessary.	
	soundFolder.postln;

...

thisProcess.nowExecutingPath returns the path to a file executing interactively by the interpreter.

when you call add on ServerBoot the function you pass as an argument is added to ServerBoot.objects - when the server boots, that function is evaluated, but it is not evaluated interactively

1 Like

Thank you very much!

I understand it word for word… However, I do not seem to really understand it because I have the following question:
Can interactivity be implemented in the future or not? Is it logical that the interpreter does not interactively evaluate the part of the code that belongs to ServerBoot.objects? Honestly, I thought it was a bug at first glance.

It’s inside a synchronous process (inside a Routine), so the language blocks the following message until the previous one is completed. With s.sync, it also ensures the server is ready.

Also remember, the server does seomthing, but you can’t forget the language, the one who is sending timed/scheduled messages to the server.

So this scheduling confusion you said is figured out by the language.

Kind of

1 Like

yes looking into it further I’m not sure I have understood it correctly!

I tried doing:

ServerTree.add({thisProcess.dump})

and doing Cmd-.

and then comparing it to thisProcess.dump

you will see that the in one case the current thread is Main with the correct nowExecutingPath and in the other it is a Routine with nowExecutingPath = nil

I’m going to read around in AbstractServerAction Kernel Thread and Main to see if I can understand this better - I think that Thread sets its executingPath via a primitive _Thread_Init and it may be that that an nil value is what we are ending up with in this case

One question here is, what are the semantics of nowExecutingPath?

  • Should it always point back to the location where the line of code was defined?
  • Or should it refer to the context at the moment of execution?

I wanted to foreground this question because it’s being assumed that the first meaning is (“obviously”?) better. Maybe…? Probably…? But it might also not be quite so obvious.

If I create a file, say, “23-1217-nowexec-proto.scd”:

(
	testFunction: {
		thisProcess.nowExecutingPath
	}
)

And a second file in the same location, “23-1217-nowexec-caller.scd”:

a = (thisProcess.nowExecutingPath.dirname +/+ "23-1217-nowexec-proto.scd").load;

a.testFunction;

… which path should be returned? “xxx-proto” or “xxx-caller”?

The current behavior is to return the caller’s path. From one point of view, that’s a stretch: the line of code accessing the current path is written into the “proto” file. But, you hit cmd-return in the caller file, and… maybe it’s useful to know that?

In any case, if it’s desired to refer always to the location where the function was defined, then I think the only solution is to move filenameSymbol out of Method and into FunctionDef, and change the C++ compiler code to fill in this variable at compile time. Then the nowExecutingPath method would have to trace back to the currently active FunctionDef.

(If a method calls nowExecutingPath, should it be the location where the method was defined, or the user code that called the method?)

Edit: Or perhaps keep both. If all functions are tagged with their path, then thisFunction.filenameSymbol would (should…?) give you the location-where-defined, and it may not be necessary to change/break the current semantic of nowExecutingPath.

A Routine’s path is set at the moment of creation.

Has your ServerTree.add code file created the routine that runs during server initialization?

Nope… so, how would the (internally-produced) Routine know about your file?

(I think the difference for Routines is that they last for a relatively long time, while Function execution is assumed to be instantaneous.)

In any case, it needs to be understood (and perhaps better documented) that nowExecutingPath operates with a synchronous time scope. It gives you access to the current user-code path (not method definitions) within the block that is running synchronously in response to a cmd-return. If that block defines actions that will happen later, nowExecutingPath does not cover this, except for Routines that are created synchronously within the block. If you need the path to be available for later operations, then (currently) it is the user’s responsibility to grab the path and stash it in a variable on their own.

hjh

3 Likes

thanks James that makes perfect sense

…indeed if I interpret

CmdPeriod.run

it does set nowExecutingPath

1 Like

I made a PR based on this thread:

If there is anything I should revise, please let me know.

Thanks for your response and advice!

The evaluation of the following code blocks in a saved scd file shows inconsistent behaviour.

Code example 1

Using thisProcess.nowExecutingPath with CmdPeriod alone, it seems to be consistent:

Step 1:

Evaluate the following code to register a functionality:

(
f = {
    ("CmdPeriod’s thisProcess.nowExecutingPath:" + thisProcess.nowExecutingPath).postln
};

CmdPeriod.add(f)
)

Step 2:

Pressing command/control + . returns (whether or not there is the startup.scd file in Platform.userAppSupportDir):

CmdPeriod’s thisProcess.nowExecutingPath: nil

Step 3:

Evaluate the following code to remove the registered functionality:

CmdPeriod.remove(f)

Step 4+:

Repeating steps 1 to 3 shows always the same behaviour.

Code example 2

The following example shows the expected behaviour only when evaluated after starting SC-IDE (or when evaluated after restarting sclang after exiting sclang using 0.exit). Repeating steps 1 to 2 again after step 3 returns nil for the thisProcess.nowExecutingPath, even though the startp.scd exists:

Step 1:

Evaluate the following code to register the functionalities after launching SC-IDE:

(
CmdPeriod.add {
	var path = thisProcess.nowExecutingPath;
	("CmdPeriod’s thisProcess.nowExecutingPath:" + path).postln
};
ServerBoot.add {
	var path = thisProcess.nowExecutingPath;
	("ServerBoot’s thisProcess.nowExecutingPath:" + path).postln
};
ServerTree.add {
	var path = thisProcess.nowExecutingPath;
	("ServerTree’s thisProcess.nowExecutingPath:" + path).postln
};
s.reboot
)

After rebooting, post window’s last two lines are as follows if there is the startup.scd file in Platform.userAppSupportDir:

ServerBoot’s thisProcess.nowExecutingPath: /Users/prko/Library/Application Support/SuperCollider/startup.scd
ServerTree’s thisProcess.nowExecutingPath: /Users/prko/Library/Application Support/SuperCollider/startup.scd

Step 2:

Pressing command/control + . returns the following if there is the startup.scd file in Platform.userAppSupportDir:

CmdPeriod’s thisProcess.nowExecutingPath: /Users/prko/Library/Application Support/SuperCollider/startup.scd
ServerTree’s thisProcess.nowExecutingPath: /Users/prko/Library/Application Support/SuperCollider/startup.scd

Step 3:

Evaluate the following code to remove the registered functionalities:

CmdPeriod.removeAll;ServerBoot.removeAll;ServerTree.removeAll

Step 4:

Evaluate the code in Step 1 of the Example 2 again. After rebooting, post window’s last two lines are as follows although there is the startup.scd file in Platform.userAppSupportDir:

ServerBoot’s thisProcess.nowExecutingPath: nil
ServerTree’s thisProcess.nowExecutingPath: nil

Step 5:

Pressing command/control + . returns the following although there is the startup.scd file in Platform.userAppSupportDir:

CmdPeriod’s thisProcess.nowExecutingPath: nil
ServerTree’s thisProcess.nowExecutingPath: nil

I have the following questions:

  • Why does pressing cmd/control + . behave differently in Example 1 and 2?
  • Why does Example 2 only show the expected behaviour the first time of evaluating after booting sclang?

I thought I understood, but today I am confused.

Thank you in advance.

nowExecutingPath isn’t fully implemented for functions.

For it to be reliable, it needs to be written like this.

(
var thisPath = thisProcess.nowExecutingPath;

f = {
    ("CmdPeriod’s thisProcess.nowExecutingPath:" + thisPath).postln
};

CmdPeriod.add(f)
)

Otherwise the behavior is not guaranteed.

That is, it’s the cases where you got the executing path that I can’t explain. The ones where you didn’t get it show the behavior I’d expect.

hjh

1 Like

Thank you!
I updated the PR: