Skip to content

[AI Refactoring] PushServerRegister/Unregister 2곳 TaskCompletionSource 의 RunContinuationsAsynchronously 누락 → 네이티브 콜백 스레드 인라인 컨티뉴에이션 [Scope: src/Tizen.Messaging.Push] (2026-07-12) #7748

Description

@JoonghyunCho

[Type: Refactoring]
[Scope: src/Tizen.Messaging.Push]
[Priority: 🔴 Critical]
[Lens: Coding Guidelines, Performance]

Observation

Both async operations in the Push binding create their TaskCompletionSource<ServerResponse> with the default constructor (no TaskCreationOptions.RunContinuationsAsynchronously), yet complete it from the native push-daemon callback thread:

src/Tizen.Messaging.Push/Tizen.Messaging.Push/PushImpl.cs:140   new TaskCompletionSource<ServerResponse>()   // PushServerRegister
src/Tizen.Messaging.Push/Tizen.Messaging.Push/PushImpl.cs:195   new TaskCompletionSource<ServerResponse>()   // PushServerUnregister

The completions happen inside the native registerResult / unregisterResult callbacks:

registerResult = (Interop.PushClient.Result regResult, IntPtr msgPtr, IntPtr userData) =>
{
    ...
    if (task.TrySetResult(response) == false) { ... }   // runs continuation inline on native thread
};
Interop.PushClient.ServiceRegister(_connection, registerResult, IntPtr.Zero);

These are surfaced by the public APIs PushClient.PushServerRegister() / PushClient.PushServerUnregister() (both Task<ServerResponse>), which apps await.

Problem

Without RunContinuationsAsynchronously, TrySetResult / SetException executes the awaiter's continuation inline on the native push callback thread.

  • Hazard (Coding Guidelines). The user continuation — which may call back into the push service or perform other blocking work — then runs on the native daemon's callback thread, risking callback-thread starvation, re-entrancy into the native stack, and deadlock if the continuation blocks on another push call.
  • Consistency. This is the exact hazard already addressed repo-wide for WiFi / Bluetooth / NFC / Remoting / IoTConnectivity bindings. Push was never updated.

Proposed Improvement

Create both native-completed TCS instances with TaskCreationOptions.RunContinuationsAsynchronously.

Before

var task = new TaskCompletionSource<ServerResponse>();

After

var task = new TaskCompletionSource<ServerResponse>(TaskCreationOptions.RunContinuationsAsynchronously);

Apply to both sites (PushServerRegister @140, PushServerUnregister @195).

Target Files

  • src/Tizen.Messaging.Push/Tizen.Messaging.Push/PushImpl.cs

Expected Impact (Quantitative Metrics)

  • Inline-continuation hazard windows on the native callback thread per async push op: 1 → 0 (continuations move to the captured context / thread pool).
  • 2 creation sites corrected; behavior-preserving; aligns Push with the existing repo-wide pattern.

API Compatibility Check

  • Public API signature change: none (Task<ServerResponse> PushServerRegister() / PushServerUnregister() unchanged).
  • Behavior change: none for correct callers — continuations no longer run inline on the native thread; returned Task result/exception unchanged.
  • Tizen API Level floor: maintained (TaskCreationOptions.RunContinuationsAsynchronously available since .NET Standard 2.0).

Impact Scope

  • 2 TCS creation sites, single assembly (internal PushImpl). Public wrappers in PushClient.cs (1 call site each) are unaffected.
  • No cross-assembly signature impact.

Auto-generated by the TizenFX AI refactoring discovery pipeline (scan date 2026-07-12).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions