[Bug 48891] Bash from Cygwin/msys2 terminates after first command

WineHQ Bugzilla wine-bugs at winehq.org
Sat May 9 01:01:34 CDT 2020


https://bugs.winehq.org/show_bug.cgi?id=48891

--- Comment #16 from Damjan Jovanovic <damjan.jov at gmail.com> ---
Cygwin's "strace" command turned out to be very useful:
strace -o ../strace.txt command

What we see, comparing dofork() in code with logging output, is that this line:
  syscall_printf ("%R = fork()", res);
logs:
... forkme 1023 ... dofork(): 0 = fork();
... forkme 1024 ... dofork(): 0 = fork();

So both the parent and the child think they are the child. Interestingly the
parent can't write to the terminal, but if you make a sample application in
which the child from fork() creates a file with the return value from
GetCurrentProcessId() in the filename, 2 files get created.

fork() calls dofork(), whose res comes from:

---snip---
    if (!ischild)
      res = grouped.parent (stackp);
    else
      {
        res = grouped.child (stackp);
        in_forkee = false;
        ischild = true; /* might have been reset by fork mem copy */
      }
---snip---

It's grouped.parent() that return 0 for the parent, and we know ischild is
correct because strace logging from grouped.parent() happens and happens only
once.

grouped.parent() is the frok::parent() method, which always return -1 on
failure. It returned 0, so it doesn't think it failed. The success return value
comes from child_pid, which is set by:

---snip---
  child_pid = cygwin_pid (pi.dwProcessId);
---snip---

pi.dwProcessId is definitely valid. What does cygwin_pid() do, that results in
it returning 0?

---snip---
/* Convert Windows WINPID into Cygwin PID.  Utilize the "winpid.WINPID"
   symlinks created for each process.  The symlink contains the Cygwin
   PID as target.  Return 0 if no "winpid.WINPID" symlink exists for
   this WINPID. */
pid_t
cygwin_pid (DWORD dwProcessId)
{
  WCHAR sym_name[24];
  WCHAR pid_name[12];
  UNICODE_STRING sym_str;
  UNICODE_STRING pid_str;
  OBJECT_ATTRIBUTES attr;
  HANDLE sym_hdl;
  NTSTATUS status;

  __small_swprintf (sym_name, L"winpid.%u", dwProcessId);
  RtlInitUnicodeString (&sym_str, sym_name);
  InitializeObjectAttributes (&attr, &sym_str, OBJ_CASE_INSENSITIVE,
                              get_shared_parent_dir (), NULL);
  status = NtOpenSymbolicLinkObject (&sym_hdl, SYMBOLIC_LINK_QUERY, &attr);
  if (!NT_SUCCESS (status))
    return 0;
  RtlInitEmptyUnicodeString (&pid_str, pid_name,
                             sizeof pid_name - sizeof (WCHAR));
  status = NtQuerySymbolicLinkObject (sym_hdl, &pid_str, NULL);
  NtClose (sym_hdl);
  if (!NT_SUCCESS (status))
    {
      system_printf ("NtOpenSymbolicLinkObject: %y, PID %u, ret 0",
                     status, dwProcessId);
      return 0;
    }
  pid_str.Buffer[pid_str.Length / sizeof (WCHAR)] = L'\0';
  pid_t ret = (pid_t) wcstoul (pid_str.Buffer, NULL, 10);
  return ret;
}
---snip---

There are 3 paths out of the function. The middle one would log an
NtOpenSymbolicLinkObject failure (it's a typo, it's actually
NtQuerySymbolicLinkObject fails), but that's not visible in the strace.
Therefore it's the first or the last return that returned 0.

So one of the following took place:
1. NtOpenSymbolicLinkObject() failed, returning 0 without logging anything.
2. NtQuerySymbolicLinkObject() succeeded but returned "0" which was parsed to 0
by wcstoul() and return to the caller, either due to a Wine bug in it, or
another Wine bug when the symbolic link was created/stored.

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.



More information about the wine-bugs mailing list