Skip to content

Fix SystemNative_IsATty P/Invoke missing on iOS/tvOS/MacCatalyst#126302

Closed
Copilot wants to merge 3 commits intomainfrom
copilot/fix-pinvoke-to-systemnative-isatty
Closed

Fix SystemNative_IsATty P/Invoke missing on iOS/tvOS/MacCatalyst#126302
Copilot wants to merge 3 commits intomainfrom
copilot/fix-pinvoke-to-systemnative-isatty

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 30, 2026

System.Diagnostics.Process has a P/Invoke to SystemNative_IsATty, but that symbol is not exported by libSystem.Native on iOS, tvOS, and Mac Catalyst, causing a runtime failure on those platforms.

Description

Guard SystemNative_IsATty in pal_console.c to unconditionally return 0 on TARGET_IOS, TARGET_TVOS, and TARGET_MACCATALYST — there is no terminal on these platforms.

int32_t SystemNative_IsATty(intptr_t fd)
{
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
    // there is no terminal on these platforms
    (void)fd;
    return 0;
#else
    return isatty(ToFileDescriptor(fd));
#endif
}

This follows the same #if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) guard pattern used elsewhere in the native libs (e.g., pal_icushim_static.c, pal_x509.c).

fixes #126299

… calling isatty

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/96c22fac-0eb4-4756-ae91-390e30c5c572

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix P/Invoke for SystemNative_IsATty in Process.dll Fix SystemNative_IsATty P/Invoke missing on iOS/tvOS/MacCatalyst Mar 30, 2026
Copilot AI requested a review from adamsitnik March 30, 2026 10:26
@adamsitnik adamsitnik marked this pull request as ready for review March 30, 2026 10:34
Copilot AI review requested due to automatic review settings March 30, 2026 10:34
Copy link
Copy Markdown
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

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

LGTM!

@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a runtime P/Invoke failure on iOS/tvOS/MacCatalyst by ensuring SystemNative_IsATty is always present in libSystem.Native, while returning a consistent “not a TTY” result on platforms where TTY semantics don’t apply.

Changes:

  • Add an Apple mobile/Catalyst preprocessor guard to SystemNative_IsATty.
  • On TARGET_IOS, TARGET_TVOS, and TARGET_MACCATALYST, return 0 without calling isatty.


int32_t SystemNative_IsATty(intptr_t fd)
{
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@rolfbjarne is this the correct fix? or is pal_console.c not compiled for iOS family because there is simply no terminal there?

Copy link
Copy Markdown
Member

@MichalStrehovsky MichalStrehovsky Mar 30, 2026

Choose a reason for hiding this comment

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

@rolfbjarne is this the correct fix? or is pal_console.c not compiled for iOS family because there is simply no terminal there?

It pulls in pal_log.m instead (the .c is only included on macOS):

if (CLR_CMAKE_TARGET_APPLE)
list (APPEND NATIVE_SOURCES_OBJC_NO_ARC
pal_autoreleasepool.m
pal_environment.m
pal_searchpath.m
pal_datetime.m)
if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
list (APPEND NATIVE_SOURCES_OBJC_NO_ARC pal_log.m)
if (CLR_CMAKE_TARGET_MACCATALYST)
list (APPEND NATIVE_SOURCES_OBJC_NO_ARC pal_iossupportversion.m)
else()
list (APPEND NATIVE_SOURCES pal_iossupportversion.c)
endif ()
elseif (CLR_CMAKE_TARGET_OSX)
list (APPEND NATIVE_SOURCES
pal_console.c
pal_log.c
pal_iossupportversion.c)
else()
message(FATAL_ERROR "Unsupported Apple platform")
endif ()
set_source_files_properties(${NATIVE_SOURCES_OBJC_NO_ARC} PROPERTIES COMPILE_FLAGS "-fno-objc-arc ${CLR_CMAKE_COMMON_OBJC_FLAGS}")
list (APPEND NATIVE_SOURCES ${NATIVE_SOURCES_OBJC_NO_ARC})
else()

The ConsolePal.iOS.cs is pretty barebones, I would look why the p/invoke is even included instead of trying to stub out.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

verify-entrypoints.sh was supposed to catch this, but we haven't turned it on for mobile. would be nice to fix that

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I've also opened #126305 to ensure I don't break any mobile platforms again (I already added tests for Android to avoid that, but missed the catalyst vs ios difference)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh the reference is from Process? Out of curiosity I had a look and...

if (PlatformDoesNotSupportProcessStartAndKill)
{
throw new PlatformNotSupportedException();
}
EnsureInitialized();
string? filename;
string[] argv;
IDictionary<string, string?> env = startInfo.Environment;
string? cwd = !string.IsNullOrWhiteSpace(startInfo.WorkingDirectory) ? startInfo.WorkingDirectory : null;
bool setCredentials = !string.IsNullOrEmpty(startInfo.UserName);
uint userId = 0;
uint groupId = 0;
uint[]? groups = null;
if (setCredentials)
{
(userId, groupId, groups) = GetUserAndGroupIds(startInfo);
}
// .NET applications don't echo characters unless there is a Console.Read operation.
// Unix applications expect the terminal to be in an echoing state by default.
// To support processes that interact with the terminal (e.g. 'vi'), we need to configure the
// terminal to echo. We keep this configuration as long as there are children possibly using the terminal.
// Handle can be null only for UseShellExecute or platforms that don't support Console.Open* methods like Android.
bool usesTerminal = (stdinHandle is not null && Interop.Sys.IsATty(stdinHandle))
|| (stdoutHandle is not null && Interop.Sys.IsATty(stdoutHandle))
|| (stderrHandle is not null && Interop.Sys.IsATty(stderrHandle));

The PlatformDoesNotSupportProcessStartAndKill at the beginning is exactly iDevices. So this should all be unreachable.

System.Diagnostic.Process already multitargets, and it already did multitarget when people added the if check. Weird. This feels like something that should be a partial class.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The PlatformDoesNotSupportProcessStartAndKill at the beginning is exactly iDevices. So this should all be unreachable.

But Process is supported on mac catalyst and not supported on iOS and tvOS:

=> (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS();

FWIW we could support it on iOS with my most recent changes (I think: #126097 (comment))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This feels like something that should be a partial class.

Let's say there is a place for improvement and I am trying really hard to make it happen right now ;P

Copy link
Copy Markdown
Member

@rolfbjarne rolfbjarne left a comment

Choose a reason for hiding this comment

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

I'm not sure I understand how this is going to fix anything, because only changing SystemNative_IsATty doesn't do anything because SystemNative_IsATty isn't built for these platforms in the first place.

int32_t SystemNative_IsATty(intptr_t fd)
{
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
// there is no terminal on these platforms
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There's a terminal on Mac Catalyst (but none on iOS or tvOS).

@adamsitnik
Copy link
Copy Markdown
Member

I'm not sure I understand how this is going to fix anything, because only changing SystemNative_IsATty doesn't do anything because SystemNative_IsATty isn't built for these platforms in the first place.

You are right, it's not going to fix the problem and that is why I've asked you to review this PR (#126302 (comment)) as I have no clue about mobile targets

@adamsitnik
Copy link
Copy Markdown
Member

Let's get the tests at least failing first in #126306

@adamsitnik adamsitnik closed this Mar 30, 2026
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.

Apple mobile: System.Diagnostics.Process.dll has P/Invoke to SystemNative_IsATty which doesn't exist

6 participants