Multithreading: Errno 9 (EBADF) – Bad File Number

If you’re randomly hitting “Bad File Number” error (Errno: 9) in a multithreaded application on Unix, then most likely you’re trapped in “Opened once but closed twice” bug.

What is this “Opened once but closed twice” bug?

Check out the below code:

foo ()
 {
     fd = open();
     // some processing.
     close (fd);
     // some processing.
     close (fd);
 }

The above code will work smoothly for a single threaded application. But in case of multithreading, if a thread “X” call open() (either in same function foo or any other function bar), when thread “Y” is in between the two close() calls, then in that case, thread “X” will get the same fd for open which thread “Y” was using (since open always return the smallest unused descriptor). File descriptors are shared by all the threads. So when thread “Y” carries out its second close(), it actually closes the file descriptor of thread “X”, which was valid & in use.

FD numbers are shared by all the threads of the same process. That means when thread “Y” closes FD number “n”, twice. Then in the second case of closing descriptor “n”, can result closing in use descriptor “n” by thread “X”. When the thread “X” starts using the descriptor “n”, it gets error – “Bad File Number” (Errno: 9).

Thus closing a descriptor twice in multithreaded application leads to random “Bad File Number” error (Errno: 9).

Windows how to find the boot disk?

Q. On a Windows server how to find which physical disk is boot disk?

Ans: diskpart.exe helps to identify which is the boot disk. Use following commands:

C:\Users\Administrator>diskpart
Microsoft DiskPart version 6.1.7601
 Copyright (C) 1999-2008 Microsoft Corporation.
 On computer: SYSTEMS11
DISKPART> list disk
  Disk ###  Status         Size     Free     Dyn  Gpt
   --------  -------------  -------  -------  ---  ---
   Disk 0    Online          465 GB  1024 KB
   Disk 1    Online          100 GB  2048 KB
   Disk 2    Online         7633 MB      0 B
DISKPART> select disk 0
Disk 0 is now the selected disk.
DISKPART> detail disk
WDC WD5000AAKX-001CA0 ATA Device
 Disk ID: 84BF18DB
 Type   : SATA
 Status : Online
 Path   : 0
 Target : 0
 LUN ID : 0
 Location Path : PCIROOT(0)#PCI(1F02)#ATA(C00T00L00)
 Current Read-only State : No
 Read-only  : No
 Boot Disk  : Yes
 Pagefile Disk  : Yes
 Hibernation File Disk  : No
 Crashdump Disk  : Yes
 Clustered Disk  : No
  Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
   ----------  ---  -----------  -----  ----------  -------  ---------  --------
   Volume 0                      NTFS   Partition    100 MB  Healthy    System
   Volume 1     C                NTFS   Partition    165 GB  Healthy    Boot
   Volume 2     S   VM           NTFS   Partition    299 GB  Healthy

The “detail disk” command outputs below parameter which identifies whether the selected disk is boot disk or not:
Boot Disk  : Yes

The disk selected in example was the boot disk, if it was not the case the output for this parameter would have been:
Boot Disk  : No

On Windows XP I observed that diskpart’s “detail disk” has no “Boot Disk” entry in the output. In that case we can check the list of volumes displayed as output of “detail disk”. The disk which contains the volumes which “Boot” volume is the boot disk.

Windows how to get type (IDE/ATA/SATA/SCSI/USB/Virtual) of physical disk?

Q. On Windows server given the physical disk \\.\PHYSICALDRIVEn identify whether the disk is ATA, SATA. SCSI disk, USB disk or it is a mounted VHD file.

Ans:
There is no straightforward way in C++ to do this. Windows provide SetupDiEnumDeviceInterfaces APIs to get the properties of devices. But I found it bit complex to solve the problem mentioned.

On the other hand diskpart.exe provides simple interface to identify the type of the disk. Use following commands to get the type of disk:

C:\Users\Administrator>diskpart
Microsoft DiskPart version 6.1.7601
 Copyright (C) 1999-2008 Microsoft Corporation.
 On computer: SYSTEMS11
DISKPART> list disk
  Disk ###  Status         Size     Free     Dyn  Gpt
   --------  -------------  -------  -------  ---  ---
   Disk 0    Online          465 GB  1024 KB
   Disk 1    Online          100 GB  2048 KB
   Disk 2    Online         7633 MB      0 B
DISKPART> select disk 0
Disk 0 is now the selected disk.
DISKPART> detail disk
WDC WD5000AAKX-001CA0 ATA Device
 Disk ID: 84BF18DB
 Type   : SATA
 Status : Online
 Path   : 0
 Target : 0
 LUN ID : 0
 Location Path : PCIROOT(0)#PCI(1F02)#ATA(C00T00L00)
 Current Read-only State : No
 Read-only  : No
 Boot Disk  : Yes
 Pagefile Disk  : Yes
 Hibernation File Disk  : No
 Crashdump Disk  : Yes
 Clustered Disk  : No
  Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
   ----------  ---  -----------  -----  ----------  -------  ---------  --------
   Volume 0                      NTFS   Partition    100 MB  Healthy    System
   Volume 1     C                NTFS   Partition    165 GB  Healthy    Boot
   Volume 2     S   VM           NTFS   Partition    299 GB  Healthy
DISKPART>

In the information provided by “detail disk” check the entry:
Type   : SATA 

If the physical disk is ATA drive the type entry in “detail disk” appear as:
Type   : ATA

If the physical disk is SCSI drive the type entry in “detail disk” appear as:
Type   : SCSI

If the physical disk is USB drive the type entry in “detail disk” appear as:
Type   : USB

If the physical disk is mounted VHD/VHDX file the type entry in “detail disk” appear as:
Type   : Virtual