Wednesday, January 30, 2008

Win32:IdentifyFile

I just uploaded my fourth Perl CPAN module to PAUSE (the Perl Author's Upload Server).

This one was written because of a conversation on perlmonks Chatterbox. A module author was bemoaning the fact that Windows files do not have an inode number. I waded in to say that they do, kinda. However it's not easy to use, and requires a C API to be called. Hence the module, written using XS.

There are two functions, IdentifyFile() and CloseIdentifyFile().

IdentifyFile() returns 3 components to uniquely identify the file or directory. In list context these are returned as a 3 item list, in scalar context they are joined together as a single string using ':'. It is therefore simple to compare two identities in perl, using 'eq'.

Just getting this information could result in a race condition. The file could be deleted, possibly by another process, between getting the information and using it in a test. Worse, another file might be created with the same file index meanwhile. To prevent this scenario, files (or directories) are opened internally by IdentifyFile(), and kept open until CloseIdentifyFile() is called (files are not physically deleted until all open file handles are closed).

I wonder how many people think of that when using an inode number on UNIX?

Wednesday, January 23, 2008

UNIX command equivalents in Perl

I realise I said I would post a new update in an ealier post. Well this is not it!
For the very latest list see my perlmonks post: UNIX command equivalents in Perl

Monday, January 21, 2008

First impressions in India

On the road again, or rather "10 cramped hours in cattle class".

My hotel is a Marriott, not everyone's cup of tea, but I think they are excellent. In my previous job we always stayed in them, nowadays I rarely get the chance; usually the hotel is um, economic. Anyway, the luxury of the hotel is in stark contrast with the surroundings. Quite a culture shock, it is like living in a travelogue.

Stereotypical taxi from the airport, including the dangly bits on the mirror. Streets being brushed by doubled-up women holding rushes, and this at 1:30 AM. The reflective safety jackets were particularly incongruous. And yes, there was even a cow in the road.

The guards, sniffer-dog, and metal detectors at the hotel entrance were a bit of a shock. The helpful and polite staff are overwhelming. I think I have said "thank-you" more than any other phrase since I got here.

Walking out of the hotel on Sunday morning I was surrounded by tricycle drivers wanting to take me for a tour. When I politely declined they disappeared, and I was not bothered again. Just outside the hotel the poverty is heart-rending, yet the busy road ignores them. I have never seen anyone riding side-saddle on a motorbike while wearing a sari before.

Friday, January 04, 2008

(Windows) What is the difference between a thread's HANDLE and its ID?

There seems to be some doubt amoung my peers over the use of a Thread ID, referred to here as a TID.

The most obvious difference between a HANDLE and a TID is that a HANDLE is specific to a process, whereas a TID is system wide.

A HANDLE is actually an unsigned int (whereas a UNIX file descriptor is a signed int) and is an index into the process's Handle Table, which is maintained by kernel.

A TID is a type of Client ID, the other type of Client ID being a PID (Process ID). TIDs and PIDs are generated in the same namespace and used by the kernel to identify these objects system wide.

So, why would you need the TID? You don't. At least, not often. A TID may be passed between processes, and another process can then get a HANDLE to that thread using the OpenThread() API.

Yes, you can manipulate threads in other processes - the caveat being that security may stop you, particularly in Windows Vista. Once you have a HANDLE to another thread you can do all those wonderful things, Suspend, Resume, Wait, GetExitCode, as you can if the thread is in the same process. One of the useful APIs in this context is PostThreadMessage(). This sentence is mis-leading, PostThreadMessage takes a TID, see comment from Hibou57 below.

BTW: make sure that HANDLE is closed, the thread cannot truly die until all HANDLEs to it are closed - that is how GetExitCodeThread() works. And you thought zombies only occurred on UNIX?

It is possible to use DuplicateHandle() to get a handle opened by another process, but that is far more painful than the MSDN implies.