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

Closed
adamsitnik with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-pinvoke-to-systemnative-isatty
Closed

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

Conversation

CopilotAI commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

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_tSystemNative_IsATty(intptr_tfd)
{
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
// there is no terminal on these platforms
(void)fd;
return0;
#elsereturnisatty(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>
CopilotAI changed the title [WIP] Fix P/Invoke for SystemNative_IsATty in Process.dllFix SystemNative_IsATty P/Invoke missing on iOS/tvOS/MacCatalystMar 30, 2026
CopilotAI requested a review from adamsitnikMarch 30, 2026 10:26
Comment threadsrc/native/libs/System.Native/pal_console.c Outdated
@adamsitnik
adamsitnik marked this pull request as ready for review March 30, 2026 10:34
CopilotAI review requested due to automatic review settings March 30, 2026 10:34

@adamsitnikadamsitnik left a 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.

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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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?

@MichalStrehovskyMichalStrehovskyMar 30, 2026

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?

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)
{
thrownewPlatformNotSupportedException();
}
EnsureInitialized();
string?filename;
string[]argv;
IDictionary<string,string?>env=startInfo.Environment;
string?cwd=!string.IsNullOrWhiteSpace(startInfo.WorkingDirectory)?startInfo.WorkingDirectory:null;
boolsetCredentials=!string.IsNullOrEmpty(startInfo.UserName);
uintuserId=0;
uintgroupId=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.
boolusesTerminal=(stdinHandleis not null&&Interop.Sys.IsATty(stdinHandle))
||(stdoutHandleis not null&&Interop.Sys.IsATty(stdoutHandle))
||(stderrHandleis 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

@rolfbjarnerolfbjarne left a 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.

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

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

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

@adamsitnik@rolfbjarne@akoeplinger@MichalStrehovsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

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

Closed
adamsitnik with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-pinvoke-to-systemnative-isatty
Closed

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

Conversation

CopilotAI commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

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_tSystemNative_IsATty(intptr_tfd)
{
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
// there is no terminal on these platforms
(void)fd;
return0;
#elsereturnisatty(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>
CopilotAI changed the title [WIP] Fix P/Invoke for SystemNative_IsATty in Process.dllFix SystemNative_IsATty P/Invoke missing on iOS/tvOS/MacCatalystMar 30, 2026
CopilotAI requested a review from adamsitnikMarch 30, 2026 10:26
Comment threadsrc/native/libs/System.Native/pal_console.c Outdated
@adamsitnik
adamsitnik marked this pull request as ready for review March 30, 2026 10:34
CopilotAI review requested due to automatic review settings March 30, 2026 10:34

@adamsitnikadamsitnik left a 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.

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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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?

@MichalStrehovskyMichalStrehovskyMar 30, 2026

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?

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)
{
thrownewPlatformNotSupportedException();
}
EnsureInitialized();
string?filename;
string[]argv;
IDictionary<string,string?>env=startInfo.Environment;
string?cwd=!string.IsNullOrWhiteSpace(startInfo.WorkingDirectory)?startInfo.WorkingDirectory:null;
boolsetCredentials=!string.IsNullOrEmpty(startInfo.UserName);
uintuserId=0;
uintgroupId=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.
boolusesTerminal=(stdinHandleis not null&&Interop.Sys.IsATty(stdinHandle))
||(stdoutHandleis not null&&Interop.Sys.IsATty(stdoutHandle))
||(stderrHandleis 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

@rolfbjarnerolfbjarne left a 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.

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

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

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

@adamsitnik@rolfbjarne@akoeplinger@MichalStrehovsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Closed
adamsitnik with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-pinvoke-to-systemnative-isatty
Closed

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

Conversation

CopilotAI commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

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_tSystemNative_IsATty(intptr_tfd)
{
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
// there is no terminal on these platforms
(void)fd;
return0;
#elsereturnisatty(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>
CopilotAI changed the title [WIP] Fix P/Invoke for SystemNative_IsATty in Process.dllFix SystemNative_IsATty P/Invoke missing on iOS/tvOS/MacCatalystMar 30, 2026
CopilotAI requested a review from adamsitnikMarch 30, 2026 10:26
Comment threadsrc/native/libs/System.Native/pal_console.c Outdated
@adamsitnik
adamsitnik marked this pull request as ready for review March 30, 2026 10:34
CopilotAI review requested due to automatic review settings March 30, 2026 10:34

@adamsitnikadamsitnik left a 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.

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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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?

@MichalStrehovskyMichalStrehovskyMar 30, 2026

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?

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)
{
thrownewPlatformNotSupportedException();
}
EnsureInitialized();
string?filename;
string[]argv;
IDictionary<string,string?>env=startInfo.Environment;
string?cwd=!string.IsNullOrWhiteSpace(startInfo.WorkingDirectory)?startInfo.WorkingDirectory:null;
boolsetCredentials=!string.IsNullOrEmpty(startInfo.UserName);
uintuserId=0;
uintgroupId=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.
boolusesTerminal=(stdinHandleis not null&&Interop.Sys.IsATty(stdinHandle))
||(stdoutHandleis not null&&Interop.Sys.IsATty(stdoutHandle))
||(stderrHandleis 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

@rolfbjarnerolfbjarne left a 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.

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

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

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

@adamsitnik@rolfbjarne@akoeplinger@MichalStrehovsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Closed
adamsitnik with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-pinvoke-to-systemnative-isatty
Closed

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

Conversation

CopilotAI commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

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_tSystemNative_IsATty(intptr_tfd)
{
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
// there is no terminal on these platforms
(void)fd;
return0;
#elsereturnisatty(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>
CopilotAI changed the title [WIP] Fix P/Invoke for SystemNative_IsATty in Process.dllFix SystemNative_IsATty P/Invoke missing on iOS/tvOS/MacCatalystMar 30, 2026
CopilotAI requested a review from adamsitnikMarch 30, 2026 10:26
Comment threadsrc/native/libs/System.Native/pal_console.c Outdated
@adamsitnik
adamsitnik marked this pull request as ready for review March 30, 2026 10:34
CopilotAI review requested due to automatic review settings March 30, 2026 10:34

@adamsitnikadamsitnik left a 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.

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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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?

@MichalStrehovskyMichalStrehovskyMar 30, 2026

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?

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)
{
thrownewPlatformNotSupportedException();
}
EnsureInitialized();
string?filename;
string[]argv;
IDictionary<string,string?>env=startInfo.Environment;
string?cwd=!string.IsNullOrWhiteSpace(startInfo.WorkingDirectory)?startInfo.WorkingDirectory:null;
boolsetCredentials=!string.IsNullOrEmpty(startInfo.UserName);
uintuserId=0;
uintgroupId=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.
boolusesTerminal=(stdinHandleis not null&&Interop.Sys.IsATty(stdinHandle))
||(stdoutHandleis not null&&Interop.Sys.IsATty(stdoutHandle))
||(stderrHandleis 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

@rolfbjarnerolfbjarne left a 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.

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

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

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

@adamsitnik@rolfbjarne@akoeplinger@MichalStrehovsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

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

Closed
adamsitnik with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-pinvoke-to-systemnative-isatty
Closed

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

Conversation

CopilotAI commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

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_tSystemNative_IsATty(intptr_tfd)
{
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
// there is no terminal on these platforms
(void)fd;
return0;
#elsereturnisatty(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>
CopilotAI changed the title [WIP] Fix P/Invoke for SystemNative_IsATty in Process.dllFix SystemNative_IsATty P/Invoke missing on iOS/tvOS/MacCatalystMar 30, 2026
CopilotAI requested a review from adamsitnikMarch 30, 2026 10:26
Comment threadsrc/native/libs/System.Native/pal_console.c Outdated
@adamsitnik
adamsitnik marked this pull request as ready for review March 30, 2026 10:34
CopilotAI review requested due to automatic review settings March 30, 2026 10:34

@adamsitnikadamsitnik left a 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.

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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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?

@MichalStrehovskyMichalStrehovskyMar 30, 2026

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?

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)
{
thrownewPlatformNotSupportedException();
}
EnsureInitialized();
string?filename;
string[]argv;
IDictionary<string,string?>env=startInfo.Environment;
string?cwd=!string.IsNullOrWhiteSpace(startInfo.WorkingDirectory)?startInfo.WorkingDirectory:null;
boolsetCredentials=!string.IsNullOrEmpty(startInfo.UserName);
uintuserId=0;
uintgroupId=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.
boolusesTerminal=(stdinHandleis not null&&Interop.Sys.IsATty(stdinHandle))
||(stdoutHandleis not null&&Interop.Sys.IsATty(stdoutHandle))
||(stderrHandleis 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

@rolfbjarnerolfbjarne left a 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.

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

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

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

@adamsitnik@rolfbjarne@akoeplinger@MichalStrehovsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Closed
adamsitnik with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-pinvoke-to-systemnative-isatty
Closed

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

Conversation

CopilotAI commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

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_tSystemNative_IsATty(intptr_tfd)
{
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
// there is no terminal on these platforms
(void)fd;
return0;
#elsereturnisatty(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>
CopilotAI changed the title [WIP] Fix P/Invoke for SystemNative_IsATty in Process.dllFix SystemNative_IsATty P/Invoke missing on iOS/tvOS/MacCatalystMar 30, 2026
CopilotAI requested a review from adamsitnikMarch 30, 2026 10:26
Comment threadsrc/native/libs/System.Native/pal_console.c Outdated
@adamsitnik
adamsitnik marked this pull request as ready for review March 30, 2026 10:34
CopilotAI review requested due to automatic review settings March 30, 2026 10:34

@adamsitnikadamsitnik left a 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.

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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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?

@MichalStrehovskyMichalStrehovskyMar 30, 2026

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?

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)
{
thrownewPlatformNotSupportedException();
}
EnsureInitialized();
string?filename;
string[]argv;
IDictionary<string,string?>env=startInfo.Environment;
string?cwd=!string.IsNullOrWhiteSpace(startInfo.WorkingDirectory)?startInfo.WorkingDirectory:null;
boolsetCredentials=!string.IsNullOrEmpty(startInfo.UserName);
uintuserId=0;
uintgroupId=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.
boolusesTerminal=(stdinHandleis not null&&Interop.Sys.IsATty(stdinHandle))
||(stdoutHandleis not null&&Interop.Sys.IsATty(stdoutHandle))
||(stderrHandleis 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

@rolfbjarnerolfbjarne left a 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.

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

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

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

@adamsitnik@rolfbjarne@akoeplinger@MichalStrehovsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

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

Closed
adamsitnik with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-pinvoke-to-systemnative-isatty
Closed

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

Conversation

CopilotAI commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

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_tSystemNative_IsATty(intptr_tfd)
{
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
// there is no terminal on these platforms
(void)fd;
return0;
#elsereturnisatty(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>
CopilotAI changed the title [WIP] Fix P/Invoke for SystemNative_IsATty in Process.dllFix SystemNative_IsATty P/Invoke missing on iOS/tvOS/MacCatalystMar 30, 2026
CopilotAI requested a review from adamsitnikMarch 30, 2026 10:26
Comment threadsrc/native/libs/System.Native/pal_console.c Outdated
@adamsitnik
adamsitnik marked this pull request as ready for review March 30, 2026 10:34
CopilotAI review requested due to automatic review settings March 30, 2026 10:34

@adamsitnikadamsitnik left a 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.

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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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?

@MichalStrehovskyMichalStrehovskyMar 30, 2026

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?

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)
{
thrownewPlatformNotSupportedException();
}
EnsureInitialized();
string?filename;
string[]argv;
IDictionary<string,string?>env=startInfo.Environment;
string?cwd=!string.IsNullOrWhiteSpace(startInfo.WorkingDirectory)?startInfo.WorkingDirectory:null;
boolsetCredentials=!string.IsNullOrEmpty(startInfo.UserName);
uintuserId=0;
uintgroupId=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.
boolusesTerminal=(stdinHandleis not null&&Interop.Sys.IsATty(stdinHandle))
||(stdoutHandleis not null&&Interop.Sys.IsATty(stdoutHandle))
||(stderrHandleis 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

@rolfbjarnerolfbjarne left a 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.

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

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

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

@adamsitnik@rolfbjarne@akoeplinger@MichalStrehovsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

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

Closed
adamsitnik with Copilot wants to merge 3 commits into
mainfrom
copilot/fix-pinvoke-to-systemnative-isatty
Closed

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

Conversation

CopilotAI commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

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_tSystemNative_IsATty(intptr_tfd)
{
#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS)
// there is no terminal on these platforms
(void)fd;
return0;
#elsereturnisatty(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>
CopilotAI changed the title [WIP] Fix P/Invoke for SystemNative_IsATty in Process.dllFix SystemNative_IsATty P/Invoke missing on iOS/tvOS/MacCatalystMar 30, 2026
CopilotAI requested a review from adamsitnikMarch 30, 2026 10:26
Comment threadsrc/native/libs/System.Native/pal_console.c Outdated
@adamsitnik
adamsitnik marked this pull request as ready for review March 30, 2026 10:34
CopilotAI review requested due to automatic review settings March 30, 2026 10:34

@adamsitnikadamsitnik left a 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.

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.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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?

@MichalStrehovskyMichalStrehovskyMar 30, 2026

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?

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)
{
thrownewPlatformNotSupportedException();
}
EnsureInitialized();
string?filename;
string[]argv;
IDictionary<string,string?>env=startInfo.Environment;
string?cwd=!string.IsNullOrWhiteSpace(startInfo.WorkingDirectory)?startInfo.WorkingDirectory:null;
boolsetCredentials=!string.IsNullOrEmpty(startInfo.UserName);
uintuserId=0;
uintgroupId=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.
boolusesTerminal=(stdinHandleis not null&&Interop.Sys.IsATty(stdinHandle))
||(stdoutHandleis not null&&Interop.Sys.IsATty(stdoutHandle))
||(stderrHandleis 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

@rolfbjarnerolfbjarne left a 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.

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

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

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

@adamsitnik@rolfbjarne@akoeplinger@MichalStrehovsky