Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support to set WorkingDirectory while running a worker #10690

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from

Conversation

siddharth-ms
Copy link
Contributor

@siddharth-ms siddharth-ms commented Dec 11, 2024

Issue describing the changes in this PR

Logic app needs this supper because PAL worker we are running as part of our PAL project, looks for .spf libraries in either in CurrentDirectory or CurrentDirectory/lib.
So we need a support in functions app to set the working directory of a worker process. Currently it defaults to function app's location.

Pull request checklist

IMPORTANT: Currently, changes must be backported to the in-proc branch to be included in Core Tools and non-Flex deployments.

  • Backporting to the in-proc branch is not required
    • Otherwise: Link to backporting PR
  • My changes do not require documentation changes
    • Otherwise: Documentation issue linked to PR
  • My changes should not be added to the release notes for the next release
    • Otherwise: I've added my notes to release_notes.md
  • My changes do not need to be backported to a previous version
    • Otherwise: Backport tracked by issue/PR #issue_or_pr
  • My changes do not require diagnostic events changes
    • Otherwise: I have added/updated all related diagnostic events and their documentation (Documentation issue linked to PR)
  • I have added all required tests (Unit tests, E2E tests)

Additional information

We have tested the changes using a worker config like below to run a pal process in Linux. Test branch la-hybrid/v4.636.1

{
  "description": {
    "language": "dotnet-isolated",
    "extensions": [
      ".dll"
    ],
    "defaultExecutablePath": "{workerDirectoryPath}lapalfe",
    "executableWorkingDirectory": "{workerDirectoryPath}",
    "defaultWorkerPath": "lapalfe"
  },
  "processOptions": {
    "initializationTimeout": "00:00:30",
    "environmentReloadTimeout": "00:00:30"
  }
}

@siddharth-ms siddharth-ms marked this pull request as ready for review December 11, 2024 08:49
@siddharth-ms siddharth-ms requested a review from a team as a code owner December 11, 2024 08:49
@jviau
Copy link
Contributor

jviau commented Dec 11, 2024

So we need a support in functions app to set the working directory of a worker process. Currently it defaults to function app's location.

Have you tried changing the working directory of your worker app once during startup from within your worker app? https://learn.microsoft.com/en-us/dotnet/api/system.io.directory.setcurrentdirectory?view=net-9.0

@siddharth-ms
Copy link
Contributor Author

So we need a support in functions app to set the working directory of a worker process. Currently it defaults to function app's location.

Have you tried changing the working directory of your worker app once during startup from within your worker app? https://learn.microsoft.com/en-us/dotnet/api/system.io.directory.setcurrentdirectory?view=net-9.0

We are trying to run PAL executable (C++ project coming from a Microsoft Reasearch to run .exe on Linux). Those executable link libraries under cwd or cwd/lib. So the app will not start until it finds and links all dependencies

@siddharth-ms siddharth-ms requested review from mathewc and removed request for mattchenderson December 12, 2024 03:32
@kshyju
Copy link
Member

kshyju commented Dec 17, 2024

To clarify, is the goal here to start a Linux executable from the host? If so, where in the environment is it located? Is this a .NET executable, and what is its specific purpose once it starts? For example, how does it initiate the dotnet isolated payload?

Could we leverage the AzureWebJobsScriptRoot environment variable to point to this executable?

@siddharth-ms
Copy link
Contributor Author

siddharth-ms commented Dec 17, 2024

To clarify, is the goal here to start a Linux executable from the host? If so, where in the environment is it located? Is this a .NET executable, and what is its specific purpose once it starts? For example, how does it initiate the dotnet isolated payload?

Could we leverage the AzureWebJobsScriptRoot environment variable to point to this executable?

Yes we want to run a linux worker on linux host. The worker will start a windows sandbox and run a .NET Framework exe.
Currently all this info is coming from worker.config.json. Like below:

{
  "description": {
    "language": "dotnet-isolated",
    "extensions": [
      ".dll"
    ],
    "defaultExecutablePath": "{workerDirectoryPath}lapalfe",
    "executableWorkingDirectory": "{workerDirectoryPath}",
    "defaultWorkerPath": "lapalfe"
  },
  "processOptions": {
    "initializationTimeout": "00:00:30",
    "environmentReloadTimeout": "00:00:30"
  }
}

The thing is, PAL, which is published by MS Research expects the dependent libraries to be part of pwd/lib or pwd. Thus we need a mechanism to set the working directory of an executable.

Everything else, as suggested in last meeting, can be done by the configs, and we have removed the flag we added before palEmulated as we don't want SKU specific code in the repo.

Regarding AzureWebjobsScriptRoot: We support multi language workers. So, we run more than one worker in single host. Like a single host can run Java, Js, and other languages as well. Thus, we want to avoid setting it for all the workers through this env var.

@jviau
Copy link
Contributor

jviau commented Dec 17, 2024

@siddharth-ms the worker.config.json allows for setting of executable working directing. Is this not sufficient for your scenario? If not, can you explain why?

@siddharth-ms
Copy link
Contributor Author

@siddharth-ms the worker.config.json allows for setting of executable working directing. Is this not sufficient for your scenario? If not, can you explain why?

Ohh, does it? How can I set the working directory?

@jviau
Copy link
Contributor

jviau commented Dec 19, 2024

@siddharth-ms the worker.config.json allows for setting of executable working directing. Is this not sufficient for your scenario? If not, can you explain why?

Ohh, does it? How can I set the working directory?

Ah I misread an existing property - nevermind.

@@ -18,6 +18,11 @@ public abstract class WorkerDescription
/// </summary>
public string DefaultExecutablePath { get; set; }

/// <summary>
/// Gets or sets the working direfory for executing worker.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spelling

@@ -59,7 +61,7 @@ internal RpcWorkerProcess(string runtime,

internal override Process CreateWorkerProcess()
{
var workerContext = new RpcWorkerContext(Guid.NewGuid().ToString(), RpcWorkerConstants.DefaultMaxMessageLengthBytes, _workerId, _workerProcessArguments, _scriptRootPath, _serverUri);
var workerContext = new RpcWorkerContext(Guid.NewGuid().ToString(), RpcWorkerConstants.DefaultMaxMessageLengthBytes, _workerId, _workerProcessArguments, _workerExecutableWorkingDirectory ?? _scriptRootPath, _serverUri);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider doing this defaulting in the ctor at the time when you set _workerExecutableWorkingDirectory

@@ -62,6 +63,23 @@ public RpcWorkerProcessTests()
testEnv,
scriptApplicationHostOptions,
new LoggerFactory());

_rpcWorkerProcessWithExecutablePath = new RpcWorkerProcess("node",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why this needs to be a field? Seems like you can just define this locally in your CreateWorkerProcess_AddsExecutableWorkingDirectory test below, since it's not used anywhere else

@@ -75,7 +93,7 @@ public void Constructor_RegistersHostStartedEvent()
return eventType == typeof(HostStartEvent);
};

_eventManager.Verify(_ => _.Subscribe(It.Is<IObserver<ScriptEvent>>(p => validate(p))), Times.Once());
_eventManager.Verify(_ => _.Subscribe(It.Is<IObserver<ScriptEvent>>(p => validate(p))), Times.AtLeastOnce());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants