Files to lib/System/Win32

From: Jeff Cohen <jeffc@jolt-lang.org>
Date: Wed, 15 Sep 2004 10:35:36 -0700

What's a "compiling mesh?"

What I meant, was that there are some implicit defines in mingw (like __GCC) and vcX (like _MVC) but possibly also other unsupported? internal structures. As I stated earlier mingw should be win32 api compliant, but not for complicating matters. But as stated earlier we should also use a true MS VC compiler as true reference.

Anyway, I suspected as much re the legal
issues.

Take these into consideration, too. :slight_smile:

Anyway, I avoided bleeding edge stuff like WOW64 for now. Still,
Signals.cpp is going to require some esoteric Structured Exception
Handling stuff and debug symbol table support. Nothing that hasn't been
around for a while, but rarely used by the typical Windows programmer.

Not an easy task. That's why I left it some code as an exercise in my first try...

Henrik

The stack tracing code requires the header files dbghelp.h and psapi.h.
The SEH stuff is declared in windows.h; if your version has
SetUnhandledExceptionFilter and SetErrorMode you should be OK.

Here's the Win32 version of Signals.cpp.

Signals.cpp (20.4 KB)

Jeff,

Thanks for the patch. It looks good except for the code copied from
Microsoft. That software is copyrighted by Microsoft and cannot be
entered into the LLVM code base without some kind of license. Was there
an MSDN license that came with this software? If so, could you please
send it to me?

Also, the formatting of that code needs to be adapted to LLVM coding
standards, like the rest of the file.

Thanks,

Reid.

No, there isn't. It was originally published in Microsoft Systems
Journal. There's no license I can find in any of the files that
accompany the article. If publication in MSJ or MSDN doesn't make it
fair game, then I guess I'll have to rewrite it.

I suspect that it's not actually a problem: MS *wants* developers to copy
the code into their proprietary apps to make them better. However, some
reassurance of this is necessary: is there something in the front of the
magazine that specifies usage rights for the code or something like that?

-Chris

I've only seen the article online. I cannot find anything that
explicitly grants permission, though my understanding is the same as
yours. So to be on the safe side, I'll rewrite it. I pretty much have
to do that anyway to make it conform to LLVM coding standards :slight_smile:

And I now realize my code has concurrency issues. What, you ask? How
can a non-threaded program like LLVM have concurrency issues? Well, on
Windows any application can find itself growing extra threads. The
culprit in this case is the console handler. If you hit CTRL/C, a new
thread magically appears to execute the handler. So the globals that
hold the list of files and directories to be deleted might be modified
in one thread as the other iterates them. Very unlikely to occur, but
theoretically possible. Have to introduce a critical section.

Oh dear.. will an exception be thrown if the file cannot be deleted
because it's currently open? Have to handle that too if so...

Microsoft is quite strict and serious about its copyright, as should
everyone be (both open source and closed source). We should always err
on the side of caution in these matters. If the material to be added to
LLVM is copyrighted and there is no *explicit* license accompanying that
copyrighted material then we must assume there is *no* license. That's a
harsh stand, but these days I think its necessary. We don't want some
SCO-like bean counter 10 years from now saying "Hey, you stole our
code".

Reid

Here's the free-of-copyrighted-Microsoft-code version of Signals.cpp.

Actually, I'm not sure if the original would work on NT/2000/XP. It was doing
stuff that's only supposed to be done on Win95/98/ME.

Signals.cpp (20.4 KB)

Uh, use this version instead... (It's way past my bedtime :))

Signals.cpp (6.32 KB)

This version has been committed to CVS with one minor change:
I made the warning about caller calling LeaveCriticalSection a little
more prominent. Patch is here:

http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20040913/018371.html

Reid.

Alas, you missed a serious bug in that same function. Patch attached to
fix it and improve some comments. No more late night coding for me :slight_smile:

That leaves Path.cpp. Once that's done I can actually try and execute
this stuff.

Signals.diff (1.54 KB)

Jeff,

Your patch has been committed.

Thanks!

Reid.

Jeff Cohen wrote:

Here's my first take on Path.cpp. It has a few holes still but it ought
to be basically functional.

A few observations:

First, the Win32 version still has a lot of code in common with Unix.
This code should be pulled out into a common file.

Second, some of the functions leave me scratching me head. What purpose
does create_file serve? Is there really a need to create empty files?
(It also leaks an open file handle, BTW). I would expect set_file to
alter only the file name portion of the path and leave the directory
portion unchanged, and the opposite for set_directory. set_directory
obliterates the file name portion of the path (OK, I guess) but set_file
doesn't make any sense at all.

Path.diff (10.5 KB)

Here's my first take on Path.cpp. It has a few holes still but it ought
to be basically functional.

A few observations:

First, the Win32 version still has a lot of code in common with Unix.
This code should be pulled out into a common file.

truly generic code (common to all platforms) should go in
lib/System/Path.cpp. If you know of such things, feel free to send
patches. FYI: I'll reject anything that has a / in a string literal.
That's not portable to all systems. While it might work on 99.9% of unix
and some modern Win32 machines, it won't work on VMS or OS/390.

Second, some of the functions leave me scratching me head. What purpose
does create_file serve? Is there really a need to create empty files?

Yes. Lock files are done this way. However, I'm not sure if LLVM uses
them.

(It also leaks an open file handle, BTW).

Oops. I'll take a look.

I would expect set_file to
alter only the file name portion of the path and leave the directory
portion unchanged, and the opposite for set_directory. set_directory
obliterates the file name portion of the path (OK, I guess) but set_file
doesn't make any sense at all.

The Path class is intended to provide path construction, not path
editing. I don't see any need for path editing in LLVM. So, "set_file"
just sets the *entire* path to a single file name. I suppose it could
prefix it with ./ on Unix since that's what it means (i.e. the directory
part is the current directory. Set directory similarly sets the *entire*
path to a single directory name. The various append_* and elide_*
functions assist with path construction, in limited ways.

set_file makes perfect sense ;>

Reid.

Patch looks good so I committed it. I'd be interested in knowing what
your test results are once you start testing with the Win32 port.

Reid.

I tested Signals.cpp and verified that the CTRL/C handler works, as does
the stack trace. In fact, here's a sample:

77E73887 (0xE06D7363 0x00000001 0x00000003 0x0012FF28), RaiseException()+0080 bytes(s)
10226DB9 (0x0012FF44 0x0040DEFC 0x00020024 0x00647373), _CxxThrowException()+0057 bytes(s)
00401822 (0x0012FFC0 0x00409A2C 0x00000001 0x003250D0), XYZ::func()+0034 bytes(s), c:\projects\llvm\test.cpp, line 12
004017ED (0x00000001 0x003250D0 0x00322C68 0x00020024), main()+0013 bytes(s), c:\projects\llvm\test.cpp, line 19
00409A2C (0x00020024 0x7FFDF000 0x7FFDF000 0xF3893CF0), mainCRTStartup()+0300 bytes(s), f:\vs70builds\3077\vc\crtbld\crt\src\crtexe.c, line 398+0017 byte(s)
77E814C7 (0x00409900 0x00000000 0x78746341 0x00000020), GetCurrentDirectoryW()+0068 bytes(s)

However, for some reason I haven't been able to determine, the lovely
trace you see above comes out only on Windows XP. On Windows 2000, it
can't get the symbol information for EXEs, though it does for DLLs. I
know this code worked on 2000 in the past, so it must be something that
broke with VC 7.1. Oh well.

(The GetCurrentDirectoryW is bogus, but the top of the stack usually is).

I did make some minor changes that I'll submit shortly.

Patch for Signals.cpp attached.

Signals.diff (3.96 KB)

Patch committed. Thanks for cleaning up some of the coding standards
issues.

Reid.

Completed testing. Diffs for Path.cpp attached to fix bugs.

Some of them are probably present in the Unix version as well.

There are some uses of ThrowError when there is no error present in
errno to format. A throw statement should be used.

Path::is_valid uses realpath on Unix. The problem is that realpath
validates that all the directory components of the path actually exist
and are executable. There are two problems with this. First, Path.h
states that is_valid does syntactic validation only. Second, it is
impossible to create a series of nested directories with
create_directory(true) as such a path would be invalid according to
realpath and hence is_valid. I changed the Win32 version to only
perform syntactic validation.

Path::create_directory had other problems. The use of path::copy to
make a local copy of the path assumed there was a null terminator.
std::string doesn't use null termination. The parsing code to identify
the intermediate directories wasn't correct either.

My first implementation of create_file was incorrect because it
succeeded even if the file already existed. I fixed that, but creating
a file to serialize concurrent programs is a Unix paradigm that is not
appropriate for all platforms. On Windows the preferred way is to use a
mutex, which cleans up after itself if a program dies abnormally.

Path.diff (5.82 KB)