Showing posts with label WinSTL. Show all posts
Showing posts with label WinSTL. Show all posts

Saturday, December 22, 2018

STLSoft 1.10.1 (beta 11) released

The latest beta of STLSoft 1.10.1 is available, at https://github.com/synesissoftware/STLSoft-1.10/tree/beta-11.

Getting the beta

As usual, there are two ways to obtain the latest beta:
  1. Select one of the release archives (.zip, .tar.gz) at https://github.com/synesissoftware/STLSoft-1.10/releases/tag/1.10.1-beta11; or
  2. Clone the repo https://github.com/synesissoftware/STLSoft-1.10 and checkout the beta-11 branch (as in "$ git checkout -b beta-10 origin/beta-11").

Changes

The substantive changes are:

  • stlsoft::ref_ptr<> class template now has two creator template functions borrow() and own();
  • winstl::environment_variable now has the additional methods:
    • data();
    • equal();
    • equal_ignore_case();
    • exists(); and
    • operator ==() and operator !=().
I'll describe these changes in a future blog post.

Friday, December 21, 2018

STLSoft 1.10.1 (beta 10) released

The latest beta of STLSoft 1.10.1 is available, at https://github.com/synesissoftware/STLSoft-1.10/tree/beta-10.

Getting the beta

As usual, there are two ways to obtain the latest beta:
  1. Select one of the release archives (.zip, .tar.gz) at https://github.com/synesissoftware/STLSoft-1.10/releases/tag/1.10.1-beta10; or
  2. Clone the repo https://github.com/synesissoftware/STLSoft-1.10 and checkout the beta-10 branch (as in "$ git checkout -b beta-10 origin/beta-10").

Changes

The substantive changes are:
  • winstl::process_mutex() now provides two additional ctor overloads that take an additional HANDLE parameter to pass an event that will be signalled in case of an ABANDONED wait, which should (almost) always be treated as a terminal condition. This means that crucial mutex instances may now be connected to a shutdown event;
  • Special String Instances - those types generated by specialisations of stlsoft::special_string_instance_0 and stlsoft::special_string_instance_1 - are now automatically provided (in)equality operators: operator ==() and operator !=(). There are a bunch of such types, including (along with all their _a and _w variants):
    • unixstl::current_directory;
    • unixstl::home_directory;
    • winstl::absolute_path;
    • winstl::current_directory;
    • winstl::home_directory;
    • winstl::host_name;
    • winstl::module_directory;
    • winstl::module_filename;
    • winstl::system_directory;
    • winstl::temporary_directory;
    • winstl::temporary_file_name;
    • winstl::user_name; and
    • winstl::windows_directory.
These will be explained below with a few short examples.

Examples

Process Mutex abandonment

The Old New Thing's "Understanding the consequences of WAIT_ABANDONED" explains the situation well, so I won't repeat here. I'll just include code from a component test for the new functionality in winstl::process_mutex():

    SECTION("waiting on an abandoned mutex with an event") {

        winstl::event         ev(true, false);

        winstl::process_mutex mx(L"my-mx", false, nullptr, ev.handle());

        CHECK(!mx.abandoned());

        std::thread thread([&] {

            mx.lock(); // acquire but don't release, then quit (=> abandon)
        });

        thread.join();

        CHECK(mx.try_lock()); // acquire, which notes the abandonment

        DWORD const r = ::WaitForSingleObject(ev.handle(), 0);

        CHECK(WAIT_OBJECT_0 == r);

        CHECK(mx.abandoned());
    }

FYI: we're changing over to using the Catch Unit-testing library for STLSoft 1.10. (Still currently using Catch v1, tho ...)

Special String Instance(s)

Simply, where (in)equality-comparison would previously have been manual tasks, as in:

  unixstl::current_directory cwd;

  if (0 == ::strcmp("/Users/matt/dev/STLSoft/Releases/1.10", cwd.c_str())
  {}

and

  winstl::current_directory cwd;

  if (0 != ::stricmp("C:\\Users\\matt\\dev\\STLSoft\\Releases\\1.10", cwd.c_str())
  {}

they are now provided with a natural syntax (due to internal use of String Access Shims):

  unixstl::current_directory cwd;

  if ("/Users/matt/dev/STLSoft/Releases/1.10" == cwd)
  {}


and

  winstl::current_directory cwd;

  if (cwd != "C:\\Users\\matt\\dev\\STLSoft\\Releases\\1.10")
  {}


Note that the case-sensitivity is handled automatically. Hence winstl::current_directory's specialising policy template now includes the member constant caseSensitive, which is now required by the special string instance class templates:

  template <typename C>
  struct cwd_policy
  {
    typedef C                         char_type;
    typedef processheap_allocator<C>  allocator_type;
    typedef size_t                    size_type;
    typedef size_type               (*pfn_type)(char_type *, size_type);

    enum { internalBufferSize       =   128 };
    enum { allowImplicitConversion  =   1   };
    enum { caseSensitive            =   0   };
    enum { sharedState              =   0   };

    static pfn_type get_fn()
    {
      return winstl::filesystem_traits::get_current_directory;
    }
  };


There's a further benefit in that the comparisons are all length-aware, so that (tiny) bit more efficient. Which is nice.






Thursday, March 4, 2010

Tuesday, February 2, 2010

Monday, May 18, 2009

WinSTL Registry library mods and fixes, part 3: exception-safety

In reviewing the implementation of the WinSTL Registry Library's winstl::basic_reg_value class - as described in part 1 and part 2 of this series of posts - I've also spotted a defect in exception-safety.

Consider the (chopped-down) definition of the basic_reg_value class:
template < . . . >
class basic_reg_value
{
. . .
private:
hkey_type    m_hkey; // The parent key of the value
string_type  m_name; // The name of the value
. . . // other members
};


The m_hkey member is obtained via winstl::reg_traits<>::reg_dup_key(). It is the basic_reg_value class itself that provides the RAII. Consequently, if any exception occur during its constructor, the release of m_hkey will not be carried out.

Since the m_name is a string class instance, its constructor can throw. Consequently, basic_reg_value is not exception safe.

Thankfully, the fix is very simple. Simply reverse the order of declaration of the two members. If m_name's constructor throws, that'll happen before the key duplication takes place. If the key duplication throws an exception, the (fully constructed) m_name's destructor will be invoked. Q.E.D.

WinSTL Registry library mods and fixes, part 2: race conditions

As discussed at great length in section 33.3 of Extended STL, volume 1, the Windows Registry API is one that is prone to race conditions, due to the fact that separate processes may make independent changes to the registry contents without any control over each other.

The recently discovered defect in the WinSTL Registry Library's winstl::basic_reg_value class, gave me cause to consider the implementation in detail again. It's been a long time since I've done that, and with the understanding of the registry race-conditions I gained while researching and writing Extended STL, I saw immediately the possibility of such a race accounting for the reported fault.

Consider again the implementation of winstl::basic_reg_value<>::value_sz() method. Assume that prior to the invocation of winstl::reg_traits<>::reg_query_info that the registry-value's value was non-zero size. The call commences. Meanwhile, another process overwrites the registry-value, with a zero size. reg_query_info returns, and indicates that the data size is zero. Without a further check on the data size, the same fault will be experienced. Naturally, the fix for the non-race defect will fix the race one as well. Which is nice.

WinSTL Registry library mods and fixes, part 1: empty values

An STLSoft user recently posted a possible defect in the implementation of the WinSTL Registry Library's winstl::basic_reg_value class, reporting that a registry value (of type REG_SZ) yields a data value of size 0, leading to a crash.

Upon first examination, I thought this was a result of the fragility of the Windows Registry with respect to race conditions, as I'll discuss in a follow-up post.

However, closer examination reveals it to be a true defect. The precise circumstances in which this occur are as follows:
  • the registry-value whose value is being elicited - as a string (REG_SZ) or as an array of strings (REG_MULTI_SZ) has zero size, and
  • it has one or more peer registry-values whose values are of non-zero size
This precise set of circumstances causes the defect to fault. The reason lies in a call to winstl::reg_traits<>::reg_query_info at the start of the winstl::basic_reg_value<>::value_sz() method. This is used to determine the maximum size of the value of any if the current key's registry-values. This is useful to be able to provide a buffer of the appropriate size to the subsequent call to winstl::reg_traits<>::reg_query_value(), which actually retrieves the value in question.

The problem occurs when the value's size is 0. The last block in the method decrements this - to account for the space for the nul-terminator added earlier - and then explicitly sets the nul-terminator. (I actually forget why it does this, but I do recall that it must be done this way.)

Anyway, when the value's size is 0, decrementing it gives a very large number, and so the next statement results in an access-violation. Yuck!

STLSoft 1.9.83 will contain the fix for this, which is simply to test again that the data size is non-0.

Friday, May 15, 2009

More 1.9.82 ...

It also includes a new method in winstl::reg_traits::reg_delete_tree(), which takes a key handle and a sub-key name, and deletes the sub-key and any/all its descendent keys, as in:

HKEY k = . . .
LONG res = winstl::reg_traits<char>::reg_delete_tree(k, "sub-key");

Use with care, because there's no un-delete!

Saturday, January 24, 2009

memcpy() / bcopy() / strncpy(): char_copy()

Well, as you've probably already noticed, I've started removing dependencies on the so-called "unsafe" string library functions from all my open-source libraries.

As part of this continuing (and somewhat life-sapping) activity, I'm moving through the STLSoft libraries. The latest release incorporates changes to the important winstl::basic_findfile_sequence class template, which is an STL extension over the Windows FindFile API.

This makes use of a new facility that's been added to the winstl::system_traits class templates: char_copy(). This (static) function is effectively a typed memcpy().


class winstl::system_traits<char>
{
. . .
public:
  char* char_copy(char* dest, char const* src, size_t n);
}

class winstl::system_traits<wchar_t>
{
. . .
public:
  wchar_t* char_copy(wchar_t* dest, wchar_t const* src, size_t n);
}


It copies exactly the number of characters specified, with no checks on the actual length of src.

The modest benefits are that it is a bit type-safe, and that you don't have to keep having to remember sizeof(char_type) * n.

I'm not totally struck on the name, and did consider borrowing other names. I liked BSD's bcopy() (to mean block copy), but it's too likely that some code somewhere #defines it to memcpy().

I'll gradually filter char_copy() throughout the rest of WinSTL, and then through UNIXSTL, as I work my way through the thankless task of getting "unsafe"-free. Ho hum.

Monday, September 15, 2008

Defect in STLSoft's Windows Registry Library on 64-bit

One of STLSoft's users is reporting weird behaviour in the Windows Registry Library, when used on 64-bit Windows (x64).

It looks like the call to winstl::dl_call is defective, since x64 does not support different calling conventions.

I must confess I'd overlooked this potential issue - in part because I've still not got around to fully implementing the STLSoft internal automated testing harness - but I would still assume that the code would work, because the calling convention information, if any, would simply be ignored.

We're still looking into it. I'll post more when I know more ...