Toggle wifi button problem

Bug #1476853 reported by Kristian Mörling
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
wicd
New
Undecided
Unassigned

Bug Description

#
# Wicd version: 1.7.3
# Distribution: Ubuntu 15.04 (vivid)
# Architecture: x86_64
# Kernel: 3.19.0-22-generic
# Python version: 2.7.9
#

If I press "Switch On Wifi", Wifi is turned on and a new button appears with the text "Switch Off Wifi". If I now press "Switch Off Wifi" the state of the wireless interface and the button remains unchanged. That is the wireless network interface is still turned on and the button does not change itself back into showing "Switch On Wifi".

After looking into the source code of wicd I noticed it's reading the output from rfkill list in order to determine if the wireless network interface is soft blocked or not (activated or not activated). If I run

   $ rfkill list

from the command line I get

   0: hci0: Bluetooth
        Soft blocked: yes
        Hard blocked: no

   1: phy0: Wireless LAN
        Soft blocked: no
        Hard blocked: no

Now if I unblock Bluetooth

   # rfkill unblock bluetooth

to give me (by executing $ rfkill list on the command line),

   0: hci0: Bluetooth
        Soft blocked: no
        Hard blocked: no

   1: phy0: Wireless LAN
        Soft blocked: no
        Hard blocked: no

, the button suddenly works as expected.

My guess is that the wifi-toggle-button-problem is a consequence of an error in the following method in wicd/networking.py.

    def GetRfKillStatus(self):
        """ Determines if rfkill switch is active or not.
        Returns:
        True if rfkill (soft-)switch is enabled.
        """
        cmd = 'rfkill list'
        rfkill_out = misc.Run(cmd)
        soft_blocks = filter(lambda x: x.startswith('Soft'),
            rfkill_out.split('\t'))
        for line in map(lambda x: x.strip(), soft_blocks):
            if line.endswith('yes'):
                return True
        return False

Since I'm not very familiar with Python (and the logic behind the lines in the original method) I pretty much rewrote the entire method. The changes seem to fix the problem, but I'm not too sure. Could someone who's better oriented in this project confirm it?

    def GetRfKillStatus(self):
        """ Determines if rfkill switch is active or not.
        Returns:
        True if rfkill (soft-)switch is enabled.
        """
        cmd = 'rfkill list wlan'
        rfkill_out = misc.Run(cmd)
        if rfkill_out.find('Soft blocked: yes') != -1:
            return True
        else:
            return False

description: updated
description: updated
description: updated
description: updated
description: updated
description: updated
description: updated
description: updated
description: updated
Revision history for this message
Kristian Mörling (testingit) wrote :

Please ignore the first solution I posted as it does not work when we're using 'WiMAX' or 'Wireless LAN'. Here's an updated version of the method.

    def GetRfKillStatus(self):
        """ Determines if rfkill switch is active or not.

        Returns:
        True if rfkill (soft-)switch is enabled.
        """
        cmd = 'rfkill list'
        types = ['Wireless LAN', 'WiMAX', 'Wireless WAN']
        rfkill_out = misc.Run(cmd).strip().split('\n')
        rfkill_out = map(lambda x: x.strip(), rfkill_out)

        # rfkill_out is empty or a list (e.g.) on the form
        # ['0: hci0: Bluetooth', 'Soft blocked: yes', 'Hard blocked: no', ...,
        # 'n: phy0: Wireless LAN', 'Soft blocked: no', 'Hard blocked: no']
        # Return True if any type is is Soft blocked.
        try:
            for index, item in enumerate(rfkill_out):
                if filter(lambda y: item.endswith(y), types):
                    if rfkill_out[index+1] == 'Soft blocked: yes':
                        return True
        except IndexError:
            pass
        return False

If any wireless network interface is soft blocked then it'll return True, otherwise False. Everything seems to work as expected now, but again I'll let someone who's more oriented in this project to be the judge of that :)

Revision history for this message
Kristian Mörling (testingit) wrote :

$ diff -ur ~/bazar/wicd/wicd/networking.py networking_fix.py

description: updated
Revision history for this message
Kristian Mörling (testingit) wrote :

I now think I got a hang of the logic and what the developer/developers was trying to make the code do in the original method; the method should return True if the first wireless interface in the list returned from 'rfkill list' is soft blocked, otherwise it should return False.

I made an update to the method using regex that will return whenever the first wireless interface returned by 'rfkill list' is soft blocked.

def GetRfKillStatus(self):
        """ Determines if rfkill switch is active or not.

        Returns:
        True if rfkill (soft-)switch is enabled.
        """
        cmd = 'rfkill list'
        types = 'Wireless LAN|WiMAX|Wireless WAN'
        rfkill_out = misc.Run(cmd)
        regex = '(?:^[0-9]+: [^:]+: (?:' + types + ')[\s]+Soft blocked:) (yes|no)$'
        m = re.search(regex, rfkill_out, re.M)
        try:
            if m and 'yes' in m.group(1):
                return True
        except IndexError:
            pass
        return False

In this comment there's a file containing the output from 'diff -ur networking.py networking_new.py.

Revision history for this message
Kristian Mörling (testingit) wrote :

Oh I just noticed, the first ?: is not necessary. The regex can be rewritten as

regex = '^[0-9]+: [^:]+: (?:' + types + ')[\s]+Soft blocked: (yes|no)$'

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.