Technically, the following is off topic for this list. But because it is about what appears to me as a done deal - something that is too late to change - I thought it might be off-topic for the main list. We can move it there if you feel that appropriate. As I understand it, 32 bit and 64 bit have to be in different directory trees, e.g., C:\cygwin and C:\cygwin64. As I understand it, that is because they both look for /bin/cygwin1.dll and avoid getting the wrong one by having different root directories. My question is why 64 bit wasn't named cygwin2.dll? 32 bit would be version 1.7.25 and the corresponding 64 bit version would be 2.7.25. Could that have allowed a single, mixed, transitional, 64-except-32-when-no-64 installation? Remember that I'm not a programmer and everything that I think that I've learned about this topic I've picked up by read the cygwin and cygwin-apps mailing lists. So this is for my education and no response is necessary. Tomorrow, Cygwin and the community that supports it will be on my list of things that I'm thankful for. TIA, - Barry Disclaimer: Statements made herein are not made on behalf of NIAID.
[-- Attachment #1: Type: text/plain, Size: 1230 bytes --] On 11/28/2013 04:11, Buchbinder, Barry (NIH/NIAID) [E] wrote: > Technically, the following is off topic for this list. But because > it is about what appears to me as a done deal - something that is too > late to change - I thought it might be off-topic for the main list. > We can move it there if you feel that appropriate. > > As I understand it, 32 bit and 64 bit have to be in different directory > trees, e.g., C:\cygwin and C:\cygwin64. As I understand it, that > is because they both look for /bin/cygwin1.dll and avoid getting the > wrong one by having different root directories. > Windows will spick the correct bitness if you have both in PATH. This is not the case if you somehow managed to install 64bit Cygwin on 32bit Windows, in which case you deserve the error :) > My question is why 64 bit wasn't named cygwin2.dll? 32 bit would > be version 1.7.25 and the corresponding 64 bit version would be > 2.7.25. Could that have allowed a single, mixed, transitional, > 64-except-32-when-no-64 installation? > Why? It is built from exactly the same sources, it is also the first version on 64bit Windows. Not to mention many programs hardcoded to load "cygwin1.dll" dynamically. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 834 bytes --]
On Thu, Nov 28, 2013 at 06:17:24AM +0800, JonY wrote:
>On 11/28/2013 04:11, Buchbinder, Barry (NIH/NIAID) [E] wrote:
>> Technically, the following is off topic for this list. But because
>> it is about what appears to me as a done deal - something that is too
>> late to change - I thought it might be off-topic for the main list.
>> We can move it there if you feel that appropriate.
>>
>> As I understand it, 32 bit and 64 bit have to be in different directory
>> trees, e.g., C:\cygwin and C:\cygwin64. As I understand it, that
>> is because they both look for /bin/cygwin1.dll and avoid getting the
>> wrong one by having different root directories.
>>
>
>Windows will spick the correct bitness if you have both in PATH. This is
>not the case if you somehow managed to install 64bit Cygwin on 32bit
>Windows, in which case you deserve the error :)
>
>> My question is why 64 bit wasn't named cygwin2.dll? 32 bit would
>> be version 1.7.25 and the corresponding 64 bit version would be
>> 2.7.25. Could that have allowed a single, mixed, transitional,
>> 64-except-32-when-no-64 installation?
>>
>
>Why? It is built from exactly the same sources, it is also the first
>version on 64bit Windows. Not to mention many programs hardcoded to load
>"cygwin1.dll" dynamically.
And, even if we had put a "cygwin2.dll" in /bin, there would still be
conflicts with the program names of all of the other programs in /bin.
cgf
[-- Attachment #1: Type: text/plain, Size: 1878 bytes --] On 11/27/2013 13:11, Buchbinder, Barry (NIH/NIAID) [E] wrote: > > My question is why 64 bit wasn't named cygwin2.dll? While I agree that there is justification for that on "different ABI" grounds, it doesn't solve the core problem. That being, the Cygwin DLL maintains a bunch of shared data structures to provide the POSIX emulation that Cygwin programs require. Different DLLs mean different memory spaces, which means two *independent* sets of these data structures. Consider a simple case: parent PID. A 64-bit Cygwin program launches a 32-bit Cygwin program. What goes getppid(2) return in the child? Take a second and think about it. Got your guess? Okay, now put the two attached C++ files into a directory that both Cygwins can see (/cygdrive/c for example) and build them. The easiest way to do that is to say "make child32" from Cygwin 32 and "make parent64" from Cygwin 64. Now from Cygwin 64, run parent64. Does the output match your guess? I bet you'll find it surprising! ------- BEGIN SPOILER -------- This happens because POSIX PIDs are in a table that lives in cygwin1.dll's memory space, and because there are two DLLs, there are two different PID tables. -------- END SPOILER --------- You don't run into this problem on "real" 32/64-bit OSes because there is only one kernel, and the 32 vs 64 bit differences are abstracted away by the syscall layer, so that everything becomes 64-bit within kernel space. There is no single central entity in Cygwin, since Cygwin runs entirely in user space. Perhaps one could build a special 32-bit cygwin1.dll that worked like Wow64[*]. It may not be possible without kernel level support, from a driver at least. On the other hand, it can't be any more tricky than building something like VirtualBox. The question then is whether it's worth the effort. [*] http://goo.gl/oYbLwg [-- Attachment #2: child32.cpp --] [-- Type: text/x-c++src, Size: 159 bytes --] #include <iostream> #include <unistd.h> int main() { std::cout << "My PID is " << getpid() << "; my parent's PID is " << getppid() << '.' << std::endl; } [-- Attachment #3: parent64.cpp --] [-- Type: text/x-c++src, Size: 460 bytes --] #include <iostream> #include <unistd.h> #include <errno.h> #include <string.h> int main() { std::cout << "My PID is " << getpid() << "; " << std::flush; switch (int pid = fork()) { case -1: // error std::cout << "ERROR: " << strerror(errno) << std::endl; break; case 0: { // child const char* cmd = "./child32"; execl(cmd, cmd, 0); break; } default: // parent std::cout << "created child PID " << pid << std::endl; } }
On Mon, Dec 02, 2013 at 12:35:00PM -0700, Warren Young wrote:
>This happens because POSIX PIDs are in a table that lives in
>cygwin1.dll's memory space, and because there are two DLLs, there are
>two different PID tables.
Actually POSIX pids are Windows PIDs. The distinction becomes fuzzy
after an exec, though, where the Cygwin PID continues to be the PID
of the process which previously exec'ed it.
cgf
On 12/2/2013 12:56, Christopher Faylor wrote:
> On Mon, Dec 02, 2013 at 12:35:00PM -0700, Warren Young wrote:
>> This happens because POSIX PIDs are in a table that lives in
>> cygwin1.dll's memory space, and because there are two DLLs, there are
>> two different PID tables.
>
> Actually POSIX pids are Windows PIDs. The distinction becomes fuzzy
> after an exec, though, where the Cygwin PID continues to be the PID
> of the process which previously exec'ed it.
Of the four PID values this pair of programs prints, shouldn't at least
two should be the same, then? I get four different values here:
PARENT: My PID is 5048; created child PID 5684
CHILD: My PID is 3108; my parent's PID is 1.
[-- Attachment #1: Type: text/plain, Size: 1416 bytes --] On 12/2/2013 13:30, Warren Young wrote: > On 12/2/2013 12:56, Christopher Faylor wrote: >> On Mon, Dec 02, 2013 at 12:35:00PM -0700, Warren Young wrote: >>> This happens because POSIX PIDs are in a table that lives in >>> cygwin1.dll's memory space, and because there are two DLLs, there are >>> two different PID tables. >> >> Actually POSIX pids are Windows PIDs. The distinction becomes fuzzy >> after an exec, though, where the Cygwin PID continues to be the PID >> of the process which previously exec'ed it. > > Of the four PID values this pair of programs prints, shouldn't at least > two should be the same, then? I get four different values here: > > PARENT: My PID is 5048; created child PID 5684 > CHILD: My PID is 3108; my parent's PID is 1. I've modified the test programs a bit. The parent can launch either a 32- or 64-bit child, and I've modified the two processes' output so they're easier to distinguish. Run without args, parent64 still runs child32, but you can now pass "64" (i.e. "./parent64 64") to make it run the new child64 program. When you do that, the output is completely sensible, unlike with the mixed bitness case: PARENT64: My PID is 8808; created child PID 3480. CHILD64: My PID is 3480; my parent's PID is 8808. Also, doesn't the fact that procps only shows processes running under the current Cygwin DLL indicate that the process table is DLL-specific? [-- Attachment #2: child32.cpp --] [-- Type: text/x-c++src, Size: 169 bytes --] #include <iostream> #include <unistd.h> int main() { std::cout << "CHILD32: My PID is " << getpid() << "; my parent's PID is " << getppid() << '.' << std::endl; } [-- Attachment #3: child64.cpp --] [-- Type: text/x-c++src, Size: 169 bytes --] #include <iostream> #include <unistd.h> int main() { std::cout << "CHILD64: My PID is " << getpid() << "; my parent's PID is " << getppid() << '.' << std::endl; } [-- Attachment #4: parent64.cpp --] [-- Type: text/x-c++src, Size: 584 bytes --] #include <iostream> #include <unistd.h> #include <errno.h> #include <string.h> int main(int argc, char* argv[]) { std::cout << "PARENT64: My PID is " << getpid() << "; " << std::flush; switch (int pid = fork()) { case -1: // error std::cout << "ERROR: " << strerror(errno) << std::endl; break; case 0: { // child const char* cmd = (argc > 1 && strcmp(argv[1], "64") == 0) ? "./child64" : "./child32"; execl(cmd, cmd, 0); break; } default: // parent std::cout << "created child PID " << pid << '.' << std::endl; } sleep(1); }
On Mon, Dec 02, 2013 at 01:30:29PM -0700, Warren Young wrote:
>On 12/2/2013 12:56, Christopher Faylor wrote:
>> On Mon, Dec 02, 2013 at 12:35:00PM -0700, Warren Young wrote:
>>> This happens because POSIX PIDs are in a table that lives in
>>> cygwin1.dll's memory space, and because there are two DLLs, there are
>>> two different PID tables.
>>
>> Actually POSIX pids are Windows PIDs. The distinction becomes fuzzy
>> after an exec, though, where the Cygwin PID continues to be the PID
>> of the process which previously exec'ed it.
>
>Of the four PID values this pair of programs prints, shouldn't at least
>two should be the same, then? I get four different values here:
>
>PARENT: My PID is 5048; created child PID 5684
>CHILD: My PID is 3108; my parent's PID is 1.
The parent pid *is* a cygwin invention (although technically it doesn't
have to be). When executed between different architectures you lose the
parent/child linkage, since as you say, the DLL in the execed process
thinks it's being started from a non-cygwin windows program.
It's a subtle distinction but there is no real table of Cygwin pids
maintained by the DLL. Each process has a shared memory region
associated with it that holds information like the parent pid. This
shared memory region is not recognized between x86/x86_64.
cgf
On Mon, Dec 02, 2013 at 04:05:51PM -0500, Christopher Faylor wrote:
>It's a subtle distinction but there is no real table of Cygwin pids
>maintained by the DLL. Each process has a shared memory region
>associated with it that holds information like the parent pid. This
>shared memory region is not recognized between x86/x86_64.
Just a further clarification for anyone who's interested: There is
a table of child pids maintained by each process. So the DLL does
maintain a list of pids. It just doesn't maintain a list of all
known Cygwin processes.
cgf