Modal Operator double keytrigger (RELEASE triggered twice on Ubuntu) here the smallest bit of code to show what I mean.

import bpy
from bpy.props import IntProperty


class ModalOperator(bpy.types.Operator):
    """Move an object with the mouse, example"""
    bl_idname = "object.modal_test_operator"
    bl_label = "AA Run"

    modal_counter = IntProperty(default=0)

    def modal(self, context, event):
        if (event.type == 'MINUS') and (event.value == 'RELEASE'):
            self.modal_counter += 1
            print('triggered!', self.modal_counter)

        elif event.type == 'LEFTMOUSE':
            print('ended by finish')
            return {'FINISHED'}

        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            print('ended by cancel')
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        self.modal_counter = 0
        print('start')
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}


def register():
    bpy.utils.register_class(ModalOperator)


def unregister():
    bpy.utils.unregister_class(ModalOperator)


if __name__ == "__main__":
    register()


The output of this operator when you press the Minus key twice is this:

start
triggered! 1     &lt;-- first press
triggered! 2     &lt;-- first press
triggered! 3     &lt;-- second press
triggered! 4     &lt;-- second press 
ended by finish


What am I doing wrong? If i set it to listen for event.value == 'PRESS' it's OK, but it seems 'RELEASE' is triggered twice?
The problem here was with the operating system /environment, and confirmed by pink-vertex. While this isn't a bug report, it may still be handy to keep around in case others experience it.
The behaviour had me stumped until I wrote the above code to localize what was happening.
This seems to be a long-standing bug in the windowing system that ubuntu uses: https://developer.blender.org/T21528 (dating:  Mar 9 2010)

knowing it's broken isn't good enough.
@NoamPeled asks how one might get a working solution in the case of the windowing system throwing multiple repeat event.values, like RELEASE -- thus  increaseing the potential for the interface to behave in unexpected ways (ie a quick tap of a key could trigger release once or twice, but mostly twice -- at the very least the lack of consistency is the true issue then)
untested and verbose,
# somewhere at the top of your python file
# add any other keys you want to track
event_values = {'MINUS': None} 

# your modal operator code (snipped for brevity, see above in the question)

    def modal(self, context, event):

        # somewhere it makes sense
        if event.type in event_values.keys():
            if event.value == event_values.get(event.type):
                pass  # or some other passthrough/ignore
            else:
                event_values[event.type] = event.value
                # do some other useful thing