Repository: archlinux/archinstall

Issue:
['/usr/bin/partprobe', '/dev/sdb'] exited with abnormal exit code [256]
I've encountered this issue while trying to install Arch from USB pendrive, using 2.4.0.RC2 version from git.
It seems to be related to the /dev/sdb pendrive.

2.3.3 version from the Arch ISO works without this problem on my laptop and goes through with the install of Arch.

Here's the logfile:
[install.log](https://github.com/archlinux/archinstall/files/8554441/install.log)

I'm not sure why partprobe has some issue with USB pendrive in 2.4.0. I'm just a noob user trying to install Arch quickly.

Thank you for archinstall, it's really nice tool :)



Discussion:
Glad you like it! We'll investigate why before we release v2.4.0! Thank you for reporting it.

Resolving patch:
diff --git a/archinstall/lib/disk/filesystem.py b/archinstall/lib/disk/filesystem.py
--- a/archinstall/lib/disk/filesystem.py
+++ b/archinstall/lib/disk/filesystem.py
@@ -11,7 +11,7 @@
 
 from .partition import Partition
 from .validators import valid_fs_type
-from ..exceptions import DiskError
+from ..exceptions import DiskError, SysCallError
 from ..general import SysCommand
 from ..output import log
 from ..storage import storage
@@ -49,7 +49,7 @@ def __exit__(self, *args :str, **kwargs :str) -> bool:
 	def partuuid_to_index(self, uuid :str) -> Optional[int]:
 		for i in range(storage['DISK_RETRY_ATTEMPTS']):
 			self.partprobe()
-			time.sleep(5)
+			time.sleep(max(0.1, storage['DISK_TIMEOUTS'] * i))
 
 			# We'll use unreliable lbslk to grab children under the /dev/<device>
 			output = json.loads(SysCommand(f"lsblk --json {self.blockdevice.device}").decode('UTF-8'))
@@ -61,8 +61,6 @@ def partuuid_to_index(self, uuid :str) -> Optional[int]:
 					if partition_uuid.lower() == uuid.lower():
 						return index
 
-			time.sleep(storage['DISK_TIMEOUTS'])
-
 		raise DiskError(f"Failed to convert PARTUUID {uuid} to a partition index number on blockdevice {self.blockdevice.device}")
 
 	def load_layout(self, layout :Dict[str, Any]) -> None:
@@ -162,11 +160,11 @@ def find_partition(self, mountpoint :str) -> Partition:
 				return partition
 
 	def partprobe(self) -> bool:
-		result = SysCommand(f'partprobe {self.blockdevice.device}')
-
-		if result.exit_code != 0:
-			log(f"Could not execute partprobe: {result!r}", level=logging.ERROR, fg="red")
-			raise DiskError(f"Could not run partprobe: {result!r}")
+		try:
+			SysCommand(f'partprobe {self.blockdevice.device}')
+		except SysCallError as error:
+			log(f"Could not execute partprobe: {error!r}", level=logging.ERROR, fg="red")
+			raise DiskError(f"Could not run partprobe on {self.blockdevice.device}: {error!r}")
 
 		return True
 
diff --git a/archinstall/lib/disk/helpers.py b/archinstall/lib/disk/helpers.py
--- a/archinstall/lib/disk/helpers.py
+++ b/archinstall/lib/disk/helpers.py
@@ -418,16 +418,20 @@ def find_partition_by_mountpoint(block_devices :List[BlockDevice], relative_moun
 			if partition.get('mountpoint', None) == relative_mountpoint:
 				return partition
 
-def partprobe() -> bool:
-	if SysCommand(f'bash -c "partprobe"').exit_code == 0:
-		time.sleep(5) # TODO: Remove, we should be relying on blkid instead of lsblk
-		return True
+def partprobe(path :str = '') -> bool:
+	try:
+		if SysCommand(f'bash -c "partprobe {path}"').exit_code == 0:
+			return True
+	except SysCallError:
+		pass
 	return False
 
 def convert_device_to_uuid(path :str) -> str:
 	device_name, bind_name = split_bind_name(path)
+
 	for i in range(storage['DISK_RETRY_ATTEMPTS']):
-		partprobe()
+		partprobe(device_name)
+		time.sleep(max(0.1, storage['DISK_TIMEOUTS'] * i)) # TODO: Remove, we should be relying on blkid instead of lsblk
 
 		# TODO: Convert lsblk to blkid
 		# (lsblk supports BlockDev and Partition UUID grabbing, blkid requires you to pick PTUUID and PARTUUID)
@@ -437,8 +441,6 @@ def convert_device_to_uuid(path :str) -> str:
 			if (dev_uuid := device.get('uuid', None)):
 				return dev_uuid
 
-		time.sleep(storage['DISK_TIMEOUTS'])
-
 	raise DiskError(f"Could not retrieve the UUID of {path} within a timely manner.")
 
 def has_mountpoint(partition: Union[dict,Partition,MapperDev], target: str, strict: bool = True) -> bool:
diff --git a/archinstall/lib/disk/partition.py b/archinstall/lib/disk/partition.py
--- a/archinstall/lib/disk/partition.py
+++ b/archinstall/lib/disk/partition.py
@@ -142,6 +142,7 @@ def end_sectors(self) -> Optional[str]:
 	def size(self) -> Optional[float]:
 		for i in range(storage['DISK_RETRY_ATTEMPTS']):
 			self.partprobe()
+			time.sleep(max(0.1, storage['DISK_TIMEOUTS'] * i))
 
 			try:
 				lsblk = json.loads(SysCommand(f"lsblk --json -b -o+SIZE {self.device_path}").decode())
@@ -154,8 +155,6 @@ def size(self) -> Optional[float]:
 				else:
 					raise error
 
-			time.sleep(storage['DISK_TIMEOUTS'])
-
 	@property
 	def boot(self) -> bool:
 		output = json.loads(SysCommand(f"sfdisk --json {self.block_device.path}").decode('UTF-8'))
@@ -194,13 +193,12 @@ def uuid(self) -> Optional[str]:
 		"""
 		for i in range(storage['DISK_RETRY_ATTEMPTS']):
 			self.partprobe()
+			time.sleep(max(0.1, storage['DISK_TIMEOUTS'] * i))
 
 			partuuid = self._safe_uuid
 			if partuuid:
 				return partuuid
 
-			time.sleep(storage['DISK_TIMEOUTS'])
-
 		raise DiskError(f"Could not get PARTUUID for {self.path} using 'blkid -s PARTUUID -o value {self.path}'")
 
 	@property
@@ -210,7 +208,14 @@ def _safe_uuid(self) -> Optional[str]:
 		This function should only be used where uuid is not crucial.
 		For instance when you want to get a __repr__ of the class.
 		"""
-		self.partprobe()
+		try:
+			self.partprobe()
+		except SysCallError as partprobe_error:
+			if self.block_device.info.get('TYPE') == 'iso9660':
+				return None
+
+			raise DiskError(f"Could not get PARTUUID of partition {self} due to partprobe error: {partprobe_error}")
+
 		try:
 			return SysCommand(f'blkid -s PARTUUID -o value {self.device_path}').decode('UTF-8').strip()
 		except SysCallError as error:
@@ -263,7 +268,6 @@ def subvolumes(self) -> Iterator[BtrfsSubvolume]:
 
 	def partprobe(self) -> bool:
 		if self.block_device and SysCommand(f'partprobe {self.block_device.device}').exit_code == 0:
-			time.sleep(1)
 			return True
 		return False
 


Test patch: